2014-01-17 98 views
0

我有一個表social_accounts與列facebook_id其中user_id IS NULL的部分索引。爲什麼Postgresql沒有在IN查詢中使用索引?

如果我做一個簡單的查詢WHERE facebook_id = '123',使用索引:

=> EXPLAIN for: SELECT "social_accounts".* FROM "social_accounts" WHERE (user_id IS NOT NULL) AND "social_accounts"."facebook_id" = '123' 
                QUERY PLAN 
-------------------------------------------------------------------------------------------------------------- 
Index Scan using index_social_accounts_on_facebook_id on social_accounts (cost=0.00..8.28 rows=1 width=345) 
    Index Cond: ((facebook_id)::text = '123'::text) 
    Filter: (user_id IS NOT NULL) 

但如果我不使用IN查詢不使用索引:爲什麼不

=> EXPLAIN for: SELECT "social_accounts".* FROM "social_accounts" WHERE (user_id IS NOT NULL) AND "social_accounts"."facebook_id" IN ('123', '456') 
              QUERY PLAN 
--------------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on social_accounts (cost=8.53..16.36 rows=2 width=345) 
    Recheck Cond: ((facebook_id)::text = ANY ('{123,456}'::text[])) 
    Filter: (user_id IS NOT NULL) 
    -> Bitmap Index Scan on index_social_accounts_on_facebook_id (cost=0.00..8.52 rows=2 width=0) 
     Index Cond: ((facebook_id)::text = ANY ('{123,456}'::text[])) 
(5 rows) 

它在第二種情況下使用索引?任何方式來加快這個查詢?

(請注意,在這個例子中我已被截斷的陣列,且我已經與許多更多元件但具有相同的,緩慢的,結果測試)

+2

你爲什麼認爲它沒有使用索引?它清楚地表明它使用'index_social_accounts_on_facebook_id上的位圖索引掃描' –

+0

好點,我不得不承認我錯過了!但是我想知道爲什麼Denis解釋過的位圖堆掃描和Recheck Cond。 – Daniel

回答

4

實際上,它是使用的索引。只是做不同的事情。

索引掃描逐一訪問行,以隨機順序從一個磁盤頁面到下一個磁盤頁面來回訪問。

位圖索引掃描首先過濾要訪問的磁盤頁面,然後依次訪問磁盤頁面。重新檢查cond是因爲在每個頁面中,您需要過濾出無效的行。

對於極少數的行,索引掃描是最便宜的。對於更多行,位圖索引掃描變得最便宜。對於更多的行,seq掃描最終會變得最便宜。

+0

謝謝你的解釋。非常豐富! – RKitson

相關問題