【问题标题】:Which column(s) to create index on for a query across multiple tables?为跨多个表的查询创建索引的列?
【发布时间】:2019-10-17 02:28:54
【问题描述】:

给定以下查询,我被要求创建一个索引来加速这个特定的查询。但是,我不确定要在哪些列上创建索引,因为查询使用多个表和列。我倾向于在 PassingStats 表上创建索引,因为它似乎在查询的 WHERE 部分中使用最多,但我不确定。这应该是非聚集索引吗?

这里是查询:

SELECT P.name, R.position, T.mascot, G.date, Stats.touchdowns
FROM Player P, PlayedFor R, Team T, Game G, PassingStats Stats
WHERE P.pid = R.pid AND R.pid = Stats.pid
    AND Stats.touchdowns >= 6
    AND (Stats.tid = G.vtid OR Stats.tid = G.htid) 
    AND (Stats.season = G.season AND Stats.week = G.week)
    AND T.tid = Stats.tid AND R.tid = Stats.tid```

Thanks in advance!

【问题讨论】:

  • 索引是在单个表上创建的,不是很多。从“id”列中假设您已经在使用一些主键列,并且这些列是自动/必要的索引。 Unclustered indexes 仅针对非整数主键实现,因此该问题的答案需要对整个架构有更深入的了解,并且不会成为单个查询优化的索引重点。
  • 您使用的是什么数据库?您标记了 sqlite 和 MySQL。
  • 如果使用 sqlite,sqlite3 shell 有a command 用于建议索引。
  • 大家好!从技术上讲,我不知道我使用的是什么数据库,因为这是我在大学学习的一般数据库课程。我认为假设 sqlite 可能是安全的,因为对于我们的编程任务,我们使用了 python 的 sqlite3 模块

标签: mysql sql sqlite indexing


【解决方案1】:

在添加索引之前,让我们先重构您的查询(如果它有所改进)。似乎您的连接表之间存在断开连接。请尝试以下查询。

SELECT p.name
    , r.position
    , t1.mascot
    , t1.date
    , t1.touchdowns
FROM Player p
INNER JOIN PlayedFor r ON p.pid = r.pid
INNER JOIN
    (SELECT s.pid, t.mascot, coalesce(g1.date, g2.date) as date, s.touchdowns
        FROM PassingStats s
        INNER JOIN Team t on t.tid = s.tid
        LEFT JOIN Game g1 on s.tid = g1.vtid and s.season = g1.season and s.week = g1.week
        LEFT JOIN Game g2 on s.tid = g2.htid and s.season = g2.season and s.week = g2.week
        WHERE s.touchdowns >= 6) as t1
    ON t1.pid = r.pid

【讨论】:

  • 嗨!您介意解释原始查询中的断开连接吗?我确实写了原始查询,所以我也很想知道我哪里出错了。您的查询似乎要复杂得多,并且可能是正确的,但我实际上无法运行这些查询,因为我没有用于这些查询的实际数据库——这只是一个问题集的假设数据库课程
  • 您的游戏表只与统计数据相关,但您将这些数据加入到您的其他表中,这就是我将其分组在子查询中的原因t1
【解决方案2】:

使用JOIN .. ON .. 语法,而不是旧的commalist 语法。完成此操作后,将很容易看出 JOINing 使用的内容与“过滤”(WHERE) 使用的内容。

我怀疑WHERE 中唯一的东西是

Stats.touchdowns >= 6

鉴于此,优化器可能使用Stats 作为第一个表,并过滤touchdowns。所以,有

INDEX(touchdowns)

可能会使用 NLJ(嵌套循环连接)访问其他表,一次一个表。

因此,请确保每个后续表都有一个索引(或PRIMARY KEY),让它使用前一个表中的值进入下一个表。

OR 是火车残骸。我不知道会发生什么来处理它。请提供EXPLAIN SELECT ...SHOW CREATE TABLE(每张桌子)。

您的问题被提出为“索引”问题。如果最终问题是关于加快查询速度,那么就说明。在这种情况下,我可能建议将OR 转换为UNION

这里介绍了简单的索引创建:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

【讨论】:

    猜你喜欢
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 2012-04-07
    相关资源
    最近更新 更多