我開始更好地掌握PostgreSQL索引,但是我遇到了OR條件的問題,在那裏我不知道該怎麼去優化我的索引以獲得更快的查詢。高級索引涉及OR-ed條件(pgsql)
我有6個條件,當單獨運行時,似乎有一個小的成本。以下是修剪查詢的示例,包括查詢計劃計算的時間。
(注:我沒有輸出低於降低複雜起見,這些查詢的實際查詢計劃,但它們都使用nested loop left joins
和index scans
,我會用正確的索引想到如果有必要,我可以包括查詢計劃爲一個更有意義的響應。)
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1)
LIMIT 10;
QUERY PLAN
-------------------------------------------------------------------------------------
Limit (cost=0.25..46.69 rows=1 width=171) (actual time=0.031..0.031 rows=0 loops=1)
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions2)
LIMIT 10;
QUERY PLAN
-------------------------------------------------------------------------------------
Limit (cost=0.76..18.97 rows=1 width=171) (actual time=14.764..14.764 rows=0 loops=1)
/* snip */
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions6)
LIMIT 10;
QUERY PLAN
-------------------------------------------------------------------------------------
Limit (cost=0.51..24.48 rows=1 width=171) (actual time=0.252..5.332 rows=10 loops=1)
我的問題是,我想與OR運算符一起參加這些6個條件,使每個條件的可能性。我的組合查詢出現更多這樣的:
EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1 OR conditions2 OR conditions3 OR conditions4 OR conditions5 OR conditions 6)
LIMIT 10;
不幸的是,這會導致查詢計劃,這似乎不再使用我的指標大幅增加(相反,選擇做一個hash left join
而非nested loop left join
,並在之前使用的index scans
上執行各種sequence scans
)。
Limit (cost=142.62..510755.78 rows=1 width=171) (actual time=30.591..30.986 rows=10 loops=1)
有沒有什麼特別的東西我應該知道關於OR-ed條件的索引以改進我的最終查詢?
UPDATE:如果我爲每個單獨的SELECT使用UNION,那似乎加快了查詢速度。但是,如果我選擇在未來,這會阻止我訂購我的結果嗎?這是我做了通過聯盟加快查詢:
EXPLAIN ANALYZE
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions1)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions2)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions3)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions4)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions5)
UNION
SELECT t1.*, t2.*, t3.*
FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
WHERE (conditions6)
LIMIT 10;
QUERY PLAN
-------------------------------------------------------------------------------------
Limit (cost=219.14..219.49 rows=6 width=171) (actual time=125.579..125.653 rows=10 loops=1)
我相信8.1改變你所指出的仍是被查詢規劃確定的,因此如果沒有出現被使用,那麼我基本上不會能夠使用它我的或條件?它看起來像我將需要使用UNION的,但它的好,知道如何通過使用括號來限制結果。謝謝! – 2009-11-05 01:58:39
另外,我沒有意識到,只有(之前8.1)的單個指數在查詢計劃中使用。這有助於我更好地理解我應該如何創建索引,所以謝謝您指出。 – 2009-11-05 02:02:27