2014-01-11 47 views
3

我有表messagesphones約6M行。而這個查詢性能比較很差Postgres緩慢的位圖堆掃描

SELECT t1.id, t2.number, t1.name, t1.gender 
     FROM messages t1 
     INNER JOIN phones t2 ON t2.id = t1.parent_id 
     INNER JOIN regions t6 ON t6.id = t1.region_id 
     WHERE t2.number IS NOT NULL AND t1.entity AND NOT t2.type AND t1.region_id = 50 
     ORDER BY t1.id LIMIT 100 

EXPLAIN ANALYZE結果:http://explain.depesz.com/s/Pd6D

對在條件的所有colums B樹索引。所有id列上的主鍵,messages表中的外鍵parent_idregion_id也是如此。所有桌子上的真空也運行。

但是在100行上超過15秒就太慢了。哪裏不對?

的Postgres 9.3,Ubuntu的13.10,CPU 2X 2.5Ghz的,4GB內存,PG配置http://pastebin.com/mPVH1YJi

+0

謝謝你提供所有需要的信息。如果我能+10而不是+1,我會。 –

+2

100行不是15秒。 對於498行(散列連接節點的結果,第5個內部)爲15秒。這就是成本所在,其餘的只是小小的工作。我會對降低random_page_cost和重新運行的結果感興趣;當測試時你做了什麼計劃?SET enable_hashjoin = off。到目前爲止,我懷疑一個合適的組合索引可能是需要的 - 我希望看到相關表索引的'\ d'輸出(不需要列)。 –

+0

無論如何,如果您在使用該信息進行編輯後發表評論,我應該能夠跟進。必須跑步。 –

回答

0

這完全取決於你的讀與寫負載,但一種解決方案可能是最常見建立複合索引/一般情況。

例如,將堆掃描轉換爲索引掃描的BTREE(parent_id,region_id)會很大。由於您有動態查詢,因此您可能需要其他幾種其他查詢可能需要的其他組合索引的其他組合,但我建議現在僅使用組合索引中的兩列(因爲每個查詢都不相同)。請注意,當只需要parent_id時,也可以掃描BTREE(parent_id,region_id),所以不需要攜帶BTREE(parent_id)索引。