2009-09-09 80 views
6

ATM我想了解如何有效地使用数据库inidices,并希望得到一些专家意见。目前我没有任何性能问题。我只是想知道,你会如何处理您的索引与此查询:如何加快此查询?

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已经是主键

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

+0

正确,但检查是否实际使用B.timestamp。 – Pomyk 2009-09-09 09:31:04

+0

每个表格有多大,以及您希望从给定查询中匹配多少行。你正在使用哪个数据库? – 2009-09-09 10:19:39

+0

另外,数据添加到表中的频率以及您希望运行查询的频率如何? – 2009-09-09 10:23:04

回答

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

您可以将索引添加到WHERE和ORDER BY子句中的所有内容中。 Ie A.event,B.event和B.timestamp。

+1

请勿盲目添加索引。见Lieven的答案。盲目添加索引可能会损害性能,因为每个索引都需要维护。在某些情况下,如小型表格,这将会伤害到IO所使用的维护可能在其他地方使用。有时,对小表进行全表扫描比索引要好。 – jim 2009-09-09 12:28:58

+0

我很想删除我的答案;然而,吉姆的评论是有用的信息,所以应该留下答案? – darasd 2009-09-09 14:09:17

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 
3

我平时努力加快我的查询

  1. 分析执行计划的时候采取这些步骤。
  2. 尝试创建(覆盖)索引以消除表扫描。
  3. 尝试创建(覆盖)索引以消除索引扫描。

至于你询问,你不会出差错创建索引上

  • A.event
  • B.event
  • B.state
  • B.Hur
+0

为B.event和B.state创建独立索引与在(B.event,B.state)上创建索引不同。区分这一点很重要,因为它对性能有直接影响。 – MatBailie 2009-09-09 10:18:02

+0

@Dems:如果在我的回答中没有说明问题,那你说的是对的。 – 2009-09-09 11:12:13

1

我会添加索引到任何加入,在where子句或按顺序by子句。

在这种情况下添加以下的索引(假设ID字段是主键和索引已经):

  1. A.event
  2. B.event
  3. B.state
  4. B.许
  5. B.event,B.timestamp(这两个字段的组合索引)

第五个,作为一个指数组合应该加快排序。

您需要调整索引的数量,防止将记录插入表中时出现的任何性能下降(添加到表中的索引越多,插入和更新就越慢,因为索引需要更新) 。

2

一个综合指数要注意的是,在索引中字段的顺序是非常重要的是很重要的。

的指标是,从某种意义上说,搜索树。如果您索引(B.event,B.state),那么树会将所有记录与保存“事件”字段组合在一起,然后通过“状态”字段对其进行排序。

如果然后来查询索引“b.state = X”,该指数将是没有多大用处的;该索引首先由“事件”排序。


在您的例子:
- 通过它过滤器A的 “事件” 字段
- 加入A.event到B.event
- 加入B.state到C.id
- 加入B.hur = D.id
- 由B.event订购,B.timestamp

重要的是要注意,优化将查看您的表和索引的统计信息,然后可能重新排列顺序连接。结果将是相同的,但顺序可能会给出不同的性能,而优化者的工作是尝试找到最佳性能。

在你的情况我希望B.event的才能是极为重要的。简单地说,因为这是结果输出的顺序,AND就是你过滤的字段。

接下来你加入B.state到C.id.因此在C.id上拥有和索引是很好的,它使联接更快。但同样,将B表数据按顺序排列好也可以使连接更快。

但是,具有上B.event的索引,并且上B.state一个单独的索引可以产生小。 B.state索引变得毫无意义,因为我们使用了B.event索引。如果将两者合并为一个索引(b.event然后是b.state),执行计划可能会找到一种方法来使用索引的b.state部分。

最后,如果将所有字段放在索引中,索引确实会变大,但查询可能永远不需要查看表格。信息在索引中。从索引到表格以找到“缺失”字段所用的时间与连接的时间相似。因此,为了读取性能,向索引添加额外的字段可能是非常有效的。

我威特灵现在,但总结是这样的:
- 通常情况下,在不同的领域不同的指数不扎堆
使用 - 对于复合索引,你指定的字段的顺序有差别
- 向索引添加'额外'字段使其更大,但也可以使查询更快
- 执行计划的顺序比查询的顺序更重要
- 但是您拥有的索引可以确定顺序执行计划

这种工作有没有绝对的答案。它非常依赖于你的数据,它更接近于艺术。

一种选择是过载使用索引表,看看产生的执行计划,并删除那些不必要的索引。

但即使有一个警告适用。因为执行计划是依赖于数据(和表格统计)的,所以在表格中有真实世界的数据是非常重要的。虽然表格有10或100行,但一个执行计划可能是最快的。但是当你得到数百万行时,执行计划可能会改变,并从不同的索引中受益。

2

运行讲解分析查询,阅读它 - 如果它不能帮助 - 把解释分析输出上explain.depesz.com,并检查它“说”。