如何加快这个查询?

时间:2009-09-09 08:56:50

标签: sql database postgresql indexing

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.idC.idD.id已经是主键

更新 通常我会把INDEX(A.event)和INDEX(B.event,B.timestamp)。它是否正确? 那么B.event,B.state和B.hur呢?

7 个答案:

答案 0 :(得分:3)

我在尝试加快查询时通常会采取以下步骤

  1. 分析执行计划。
  2. 尝试创建(覆盖)索引以消除表扫描。
  3. 尝试创建(覆盖)索引以消除索引扫描。
  4. 至于您的查询,在

    上创建索引不会出错
    • A.event
    • B.event
    • B.state
    • B.Hur

答案 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字段是主键并已编入索引):

  1. A.event
  2. B.event
  3. B.state
  4. B.Hur
  5. B.event,B.timestamp(两个领域的综合指数)
  6. 作为索引组合的第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