2011-06-21 99 views
4

下面是一个postgres查询,似乎比我预期的要长得多。 field_instances表在form_instance_id和field_id上都被索引,而form_instances表则在workflow_state上被索引。所以我认为这将是一个快速查询,但它需要永远。任何人都可以帮助我解释查询计划以及添加哪些索引来加速它?谢谢。如何优化这个postgresql查询?

explain analyze 
select form_id,form_instance_id,answer,field_id 
from form_instances,field_instances 
where workflow_state = 'DRqueued' 
    and form_instance_id = form_instances.id 
    and field_id = 'Book_EstimatedDueDate'; 
                       QUERY PLAN                     
------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Hash Join (cost=8733.85..95692.90 rows=9277 width=29) (actual time=2550.000..15430.000 rows=11431 loops=1) 
    Hash Cond: (field_instances.form_instance_id = form_instances.id) 
    -> Bitmap Heap Scan on field_instances (cost=2681.11..89071.72 rows=47567 width=25) (actual time=850.000..13690.000 rows=51726 loops=1) 
     Recheck Cond: ((field_id)::text = 'Book_EstimatedDueDate'::text) 
     -> Bitmap Index Scan on index_field_instances_on_field_id (cost=0.00..2669.22 rows=47567 width=0) (actual time=830.000..830.000 rows=51729 loops=1) 
       Index Cond: ((field_id)::text = 'Book_EstimatedDueDate'::text) 
    -> Hash (cost=5911.34..5911.34 rows=11312 width=8) (actual time=1590.000..1590.000 rows=11431 loops=1) 
     -> Bitmap Heap Scan on form_instances (cost=511.94..5911.34 rows=11312 width=8) (actual time=720.000..1570.000 rows=11431 loops=1) 
       Recheck Cond: ((workflow_state)::text = 'DRqueued'::text) 
       -> Bitmap Index Scan on index_form_instances_on_workflow_state (cost=0.00..509.11 rows=11312 width=0) (actual time=650.000..650.000 rows=11509 loops=1) 
        Index Cond: ((workflow_state)::text = 'DRqueued'::text) 
Total runtime: 15430.000 ms 
(12 rows) 
+0

你可以尝试像'设置ENABLE_HASHJOIN = 0;',看看是否有为您提供更快的计划。如果确实如此,那么我们将继续检查为什么该计划没有被首先使用。 – sayap

+0

一些事情。这是什么版本的pg,并且您是否尝试了一下work_mem(比如说16MB左右)?哦,我们可以得到表格的模式,还是完全合格的列名称,当我不知道哪些列来自哪个表时,有点令人困惑。另外,你有没有尝试过使用显式连接语法? (即从一个加入b(ax =) –

回答

4

当你说的field_instances表索引上都form_instance_id和FIELD_ID你的意思是有关于form_instance_id和FIELD_ID该表上的单独的索引?

尝试在form_instance_id删除索引,并把级联指数(form_instance_id, field_id)

一个索引通过给你一个快速查找来告诉你哪些行匹配你的索引。然后它必须通过这些行来完成你想要的操作。所以你总是希望你的索引尽可能具体。如果您在表格中放置两个索引,您将有两种不同的方式来执行查找,但查询通常只会利用其中的一种。如果您在表格上连接连接的索引,则可以高效地查找索引中的第一个字段,前两个字段等。 (所以在(a, b)级联指数给出了两个aba您快速查找,甚至更快的查找速度,但不会帮你找东西上b

现在它在form_instances找出所有可能的事那有正确的状态。它分别计算出所有具有正确字段ID的field_instances。然后它做一个散列连接。为此,从一个结果集中进行查找哈希,并扫描另一个查找匹配结果。

我的建议应该找出相关的所有form_instances。然后它将转到索引,并找出与匹配的所有field_instances,这两个表单实例和字段ID都匹配,然后它将找到所需的结果。由于索引更具体,因此数据库将有更少的数据行来处理查询。

+0

+1 - 这似乎是提供的信息的问题的最佳解决方案 - 手指交叉! –

+0

正如你怀疑,我有两个单独的索引,一个用于form_instance_id和一个但是,我遵循你的建议,并删除了form_instance_id索引,并在(form_instance_id,field_id)上创建了新的索引,但它没有什么不同,新计划似乎甚至没有使用而是使用我为不同的查询创建的不同索引(answer,field_id) – zippy

+0

@zippy:好的,现在PostgreSQL优化器只是在做一些愚蠢的事情,我需要有权访问系统玩弄它一段时间,找出它为什么如此愚蠢,并找出如何欺骗它做正确的事情。对不起,我不能有更多的帮助。 – btilly

1

http://explain.depesz.com是一个梦幻般的在线工具,帮助您识别热点视觉。我贴你的结果到工具和得到这个分析:http://explain.depesz.com/s/VIk

很难明确告诉任何东西,没有看到你的表和索引,但是。

+0

我们被告知所有我们需要的信息ab out表和索引。也知道它将所有的时间花在散列连接上并没有告诉我们如何摆脱散列连接。 – btilly

+1

为链接+1。 – youngthing

0

需要知道你在你的表有数据但刚刚从看SQL和列名,我会建议

  1. 你真的需要上workflow_state假设其内部元素不能很索引独特的 - 这可能不会提高选择,但将插入或更新...
  2. 尝试使field_id检查的第一个条件在WHERE语句