2017-02-02 22 views
0

我試圖優化這個查詢:的Postgres選擇一個aweful查詢計劃,那怎麼可以固定

EXPLAIN ANALYZE 
select 
    dtt.matching_protein_seq_ids 
from detected_transcript_translation dtt 
join peptide_spectrum_match psm 
    on psm.detected_transcript_translation_id = 
     dtt.detected_transcript_translation_id 
join peptide_spectrum_match_sequence psms 
    on psm.peptide_spectrum_match_sequence_id = 
     psms.peptide_spectrum_match_sequence_id 
WHERE 
dtt.matching_protein_seq_ids && ARRAY[654819, 294711] 
; 

當seq_scan被允許(設置ENABLE_SEQSCAN = ON),優化器選擇一個很可怕的計劃,在49.85秒運行:

https://explain.depesz.com/s/WKbew

隨着集ENABLE_SEQSCAN =關,所選擇的計劃使用正確的索引和查詢instantely運行。

https://explain.depesz.com/s/ISHV

注意,我並運行分析有關的所有三個表...

回答

0

您的問題是PostgreSQL的無法估計的WHERE條件很好,所以估計它作爲估計的一定比例總行數,這太多了。

如果您知道那總會有一些成績排像這樣的查詢,你可以通過定義一個函數

CREATE OR REPLACE FUNCTION matching_transcript_translations(integer[]) 
    RETURNS SETOF detected_transcript_translation 
    LANGUAGE SQL 
    STABLE STRICT 
    ROWS 2 /* pretend there are always exactly two matching rows */ 
AS 
'SELECT * FROM detected_transcript_translation 
    WHERE matching_protein_seq_ids && $1'; 

你可以使用像

select 
    dtt.matching_protein_seq_ids 
from matching_transcript_translations(ARRAY[654819, 294711]) dtt 
join peptide_spectrum_match psm 
    on psm.detected_transcript_translation_id = 
     dtt.detected_transcript_translation_id 
join peptide_spectrum_match_sequence psms 
    on psm.peptide_spectrum_match_sequence_id = 
     psms.peptide_spectrum_match_sequence_id; 

然後PostgreSQL的欺騙應該被認爲會有一個匹配的行。

但是,如果有很多匹配的行,那麼最終的計劃將會比您當前的計劃更糟糕。