ATM我正在努力学习如何有效地使用数据库知识,并希望获得一些专家意见。我目前没有任何性能问题。我想知道,你将如何使用此查询处理索引:
SELECT B.event,
COALESCE(B.system, C.surname || ' ' || C.forename) AS name,
C.label,
B.timestamp
FROM A
INNER JOIN B ON A.event=B.event
INNER JOIN C ON B.state=C.id
LEFT OUTER JOIN D ON B.hur=D.id
WHERE A.id IN(12,13,14,15,...)
ORDER BY B.event, B.timestamp
A.id
,C.id
和D.id
已经是主键
更新 通常我会把INDEX(A.event)和INDEX(B.event,B.timestamp)。它是否正确? 那么B.event,B.state和B.hur呢?
答案 0 :(得分:3)
我在尝试加快查询时通常会采取以下步骤
至于您的查询,在
上创建索引不会出错答案 1 :(得分:3)
重写您的查询:
SELECT B.event,
COALESCE(B.system, C.surname || ' ' || C.forename) AS name,
C.label,
B.timestamp
FROM B
INNER JOIN
C
ON C.id = B.state
LEFT OUTER JOIN
D
ON D.id = B.hur
WHERE B.event IN
(
SELECT event
FROM A
WHERE A.id IN (12, 13, 14, 15)
)
ORDER BY
B.event, B.timestamp
,并在B (event, timestamp)
答案 2 :(得分:2)
您可以为WHERE和ORDER BY子句中的所有内容添加索引。即A.event,B.event和B.timestamp。
答案 3 :(得分:2)
重要的是要注意索引中字段的顺序很重要。
索引在某种意义上是搜索树。如果您索引(B.event,B.state),那么树将使用save“event”字段将所有记录组合在一起,然后按“state”字段对它们进行排序。
如果您当时要查询“b.state = x”的索引,那么该索引几乎没用;索引首先按“事件”排序。
在你的例子中:
- 通过它的“事件”字段过滤A.
- 将A.event加入B.event
- 加入B.state到C.id
- 加入B.hur = D.id
- 由B.event,B.timestamp
重要的是要注意,优化将查看表和索引的统计信息,然后可以重新排列连接的顺序。结果将是相同的,但订单可能会提供不同的性能,优化工作的目的是尝试找到最佳性能。
在你的情况下,我希望B.event的命令非常重要。只是因为那是结果输出的顺序,而它是你过滤的字段。
接下来,您将B.state加入C.id.因此拥有和索引C.id是好的,它使连接更快。但同样地,以良好的顺序使B表数据也可以使连接更快。
但是,拥有B.event的索引和B.state的单独索引可能收效甚微。 B.state索引变得毫无意义,因为我们正在使用B.event索引。如果将两者合并为一个索引(b.event然后是b.state),执行计划可能会找到一种方法来使用索引的b.state部分。
最后,如果将所有字段放在索引中,索引确实会变大,但查询可能永远不需要查看表。信息在索引中。从索引到表以查找“缺失”字段所花费的时间与连接类似。因此,对于读取性能,向索引添加额外字段可能非常重要。
我现在很烦,但总结如下:
- 通常,单独字段上的单独索引不会一起使用
- 对于复合索引,指定字段的顺序会有所不同
- 向索引添加“额外”字段会使其更大,但也可以更快地进行查询
- 执行计划的顺序比您的查询顺序更重要
- 但您拥有的索引可以确定执行计划的顺序
这种工作没有明确的答案。它依赖于您的数据,更接近艺术。
一种选择是使用索引过载表,查看生成的执行计划,并删除不必要的索引。
但即使有一点需要注意。由于执行计划依赖于数据(和表统计信息),因此在表中包含真实世界数据非常重要。虽然表有10'或100行,但一个执行计划可能最快。但是,当您获得数百万行时,执行计划可能会发生变化,因此可以从不同的索引中获益。
答案 4 :(得分:2)
运行解析分析查询,并阅读它 - 如果没有帮助 - 将解析分析输出放在explain.depesz.com上并检查它“说”的内容。
答案 5 :(得分:1)
我会在where子句或order by子句中为索引添加索引。
在这种情况下,添加以下索引(假设ID字段是主键并已编入索引):
作为索引组合的第5个应该加快顺序。
您需要调整索引的数量,以防止在将记录插入表中时出现的任何性能下降(添加到表中的索引越多,插入和更新就越慢,因为索引需要更新)。
答案 6 :(得分:0)
SELECT B.event, B.system, COALESCE(C.surname) || ' ' || COALESCE(C.forename) AS name, C.label, B.timestamp
FROM A
INNER JOIN B ON A.event=B.event
INNER JOIN C ON B.state=C.id
LEFT OUTER JOIN D ON B.hur=D.id
WHERE A.event = ANY(:visits)
ORDER BY B.event, B.timestamp
ORDER BY也会严重降低速度。 确保将其编入索引:
A.event
B.event
B.state
C.id
B.timestamp