2011-06-21 144 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語句