2011-12-15 53 views
5

我有如下表:Postgres - 這是在布爾列上創建部分索引的正確方法嗎?

CREATE TABLE recipemetadata 
(
    --Lots of columns 
    diet_glutenfree boolean NOT NULL, 
); 

大多數,除非有人能拿出符合席捲全國一些瘋狂的新的無麩質飲食的每一行都將被設置爲FALSE

我需要能夠非常快速地查詢這個值爲真的行。我創建了索引:

CREATE INDEX IDX_RecipeMetadata_GlutenFree ON RecipeMetadata(diet_glutenfree) WHERE diet_glutenfree; 

這似乎是工作,但我無法弄清楚如何判斷它的確唯一索引行,其中的值是true。我想確保它沒有做任何愚蠢的事情,比如索引任何具有任何值的行。

我應該在WHERE子句中添加一個運算符,還是該語法完全有效?希望這不是那些超級簡單的RTFM問題,它將被壓低30次。

UPDATE:

我已經先行一步,並添加10,000行到RecipeMetadata隨機值。然後我在桌子上做了一次ANALYZE,然後做了一次REINDEX。當我運行查詢:

select recipeid from RecipeMetadata where diet_glutenfree;

我得到:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=5010 width=16)' 
' Filter: diet_glutenfree' 

所以,這似乎是在做一個順序掃描在桌子上,即使只有大約一半的行具有該標誌。索引被忽略。

如果我做的:

select recipeid from RecipeMetadata where not diet_glutenfree;

我得到:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=5016 width=16)' 
' Filter: (NOT diet_glutenfree)' 

所以不管是什麼,不使用此索引。

+1

請從檔案中添加一個PostgreSQL郵件列表文章的鏈接,以便人們可以將此討論與該討論聯繫起來。如果您將郵件列表帖子的鏈接發佈到此郵件列表中,那就太好了。如果你要在多個地方交叉發帖,請這麼說,以防止人們重複工作。 – 2011-12-15 05:45:00

+0

不是問題,我將來會這樣做(我通常不會在這兩個地方發帖)。 – 2011-12-15 05:47:35

+0

順便說一句,我認爲你的問題的簡短答案是「是」...但如果你擔心,用一些虛擬數據填充一個表,`ANALYZE`表,然後使用`EXPLAIN ANALYZE`來檢查一些查詢的計劃,這些查詢應該會觸及部分索引。 – 2011-12-15 05:56:20

回答

4

我已經確認索引按預期工作。

我重新創建隨機數據,只是這一次設置diet_glutenfreerandom() > 0.9所以有隻有一個on位的10%的機會。

然後我重新創建索引並再次嘗試查詢。

SELECT RecipeId from RecipeMetadata where diet_glutenfree; 

返回:

'Index Scan using idx_recipemetadata_glutenfree on recipemetadata (cost=0.00..135.15 rows=1030 width=16)' 
' Index Cond: (diet_glutenfree = true)' 

和:

SELECT RecipeId from RecipeMetadata where NOT diet_glutenfree; 

返回:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=8996 width=16)' 
' Filter: (NOT diet_glutenfree)' 

看來我的第一次嘗試被污染了,因爲PG估計它的速度更快掃描整個表而不是擊中inde x如果它必須加載超過一半的行。

但是,我想我會在列的完整索引上得到這些確切的結果。有沒有辦法來驗證索引在部分索引中的行數?

UPDATE

指數約爲40K。我創建了同一列的完整索引,它超過了200k,因此它看起來好像是部分的。

1

一位字段上的索引是沒有意義的。爲了理解規劃者做出的決定,你必須按照頁面而不是按行來考慮。

對於8K頁和80(行)的行大小,每頁有100行。假設隨機分佈,一個頁面只包含true值的行的機會是可忽略的,pow (0.5, 100),大約1e-33,IICC。 (當然對於'錯誤'當然是相同的)因此對於在gluten_free == true,上的查詢,每個頁面都必須被提取,然後過濾。使用索引只會導致更多頁面(:索引)被提取。

相關問題