2011-12-15 55 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,上的查询,每个页面都必须被提取,然后过滤。使用索引只会导致更多页面(:索引)被提取。

相关问题