2011-05-04 73 views
1

我有以下查詢:Postgres的嵌套循環順序

SELECT t1.c1 FROM t1,t2 WHERE t1.c2 = 'X' AND t1.id = t2.id AND t2.c3 = 'Y'; 

Postgres的產生兩個計劃,該查詢,像:

Nested Loop (rows=1 width=7) (actual rows=1 loops=1) 
    -> Index Scan using idx1 on t1 (rows=1 width=7) (actual rows=4 loops=1) 
    -> Index Scan using idx2 on t2 (rows=1 width=7) (actual rows=0 loops=7) 

或:

Nested Loop (rows=1 width=7) (actual rows=1 loops=1) 
    -> Index Scan using idx2 on t2 (rows=4 width=7) (actual rows=1000000 loops=1) 
    -> Index Scan using idx1 on t1 (rows=1 width=7) (actual rows=0 loops=1000000) 

所以,有時t1被選擇用於外部循環,有時是t2。如果選擇第二個計劃,那麼表現絕對糟糕。

我的問題是,我如何強制Postgres總是使用第一個查詢計劃,在外循環t1?

回答

1

確保您正在定期運行ANALYZE。估計結果不大。

BTW,Postgres將可能不在乎,但你可能

SELECT T1.c1 FROM t1 JOIN t2 ON t1.id=t2.id 
WHERE t1.c2='X' AND t2.c3='Y'; 
+0

ANALYZE是跑了定期,有可能是一些調整,我可以在那邊做,但我在想,如果無論如何,我可以強制嵌套循環順序,因爲我不知道ANALYZE將解決問題。我嘗試使用JOIN,但得到了相同的結果。 – dandu 2011-05-05 00:03:28

+0

除非您已經簡化了這種情況,否則在本例中ANALYZE尚未運行。 t2的估計行數減少了25萬倍。或者c2和c3的分佈很不平衡。你可以嘗試用半聯接't1 NATURAL JOIN(SELECT * FROM t2 WHERE t2.c3 ='Y')AS t3 WHERE'來重寫這個,但是請注意,如果c2和c3的分佈相反,你會想要第二個計劃,而不是第一個計劃! – 2011-05-05 00:14:27

+0

這個例子確實簡化了。我會嘗試半連接。 – dandu 2011-05-05 00:22:28

0

試圖用左連接取得更好的成績?這應該強制連接順序和返回,因爲在t2.c3的條款相同的結果:

SELECT t1.c1 
FROM t1 LEFT JOIN t2 ON t1.id = t2.id 
WHERE t1.c2 = 'X' AND t2.c3 = 'Y';