如何优化此postgresql查询?

时间:2011-06-21 21:31:00

标签: postgresql

以下是一个postgres查询,似乎比我预期的要长得多。 field_instances表在form_instance_id和field_id上编制索引,form_instances表在workflow_state上编制索引。所以我认为这将是一个快速的查询,但它需要永远。任何人都可以帮我解释查询计划以及要添加哪种索引以加快速度吗?感谢。

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)

3 个答案:

答案 0 :(得分:4)

当你说 field_instances_id和field_id 上的field_instances表被编入索引时,你的意思是该表上的form_instance_id和field_id上有单独的索引?

尝试删除form_instance_id上的索引并在(form_instance_id, field_id)上添加连锁索引。

索引的工作原理是为您提供快速查找,告诉您哪些行与您的索引匹配。然后它必须通过这些行来执行您想要的操作。因此,您始终希望索引尽可能具体。如果在表上放置两个索引,则有两种不同的方法可以进行查找,但查询通常只会利用其中一个。如果在表上放置连接索引,您将能够有效地查找索引中的第一个字段,前两个字段等。 (因此(a, b)上的连锁索引可以让您快速查找a,更快地查找ab,但无法帮助您查看b {1}})

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

根据我的建议,它应该找出所有可能感兴趣的form_instances。然后它将转到索引,并找出匹配两者表单实例和字段ID的所有field_instances,然后它将找到确切感兴趣的结果。由于索引更具体,因此数据库将有更少的数据行来处理您的查询。

答案 1 :(得分:1)

http://explain.depesz.com是一款出色的在线工具,可帮助您直观地识别热点。我将您的结果粘贴到工具中并进行了此分析:http://explain.depesz.com/s/VIk

然而,如果没有看到你的表格和索引,很难说清楚。

答案 2 :(得分:0)

需要知道你的表中的数据,但只需查看我推荐的sql和列名称

  1. 你真的需要一个关于workflow_state的索引,假设其中的元素不是很独特 - 这可能不会改进select但会插入或更新......
  2. 尝试field_id检查where语句中的第一个条件