Postgres - 这是在布尔列上创建部分索引的正确方法吗?

Mik*_*sen 6 sql postgresql postgresql-9.1

我有下表:

CREATE TABLE recipemetadata
(
  --Lots of columns
  diet_glutenfree boolean NOT NULL,
);
Run Code Online (Sandbox Code Playgroud)

大多数每一行都将被设置为FALSE除非有人提出一些疯狂的新无麸质饮食,扫除了整个国家.

我需要能够非常快速地查询此值为true的行.我创建了索引:

CREATE INDEX IDX_RecipeMetadata_GlutenFree ON RecipeMetadata(diet_glutenfree) WHERE diet_glutenfree;
Run Code Online (Sandbox Code Playgroud)

它似乎工作,但我无法弄清楚如何确定它是否只是索引值为true的行.我想确保它没有像使用任何值索引任何行一样愚蠢.

我应该在WHERE子句中添加运算符,还是这种语法完全有效?希望这不是那些超级简单的RTFM问题之一,将被投票30次.

更新:

我已经使用随机值向RecipeMetadata添加了10,000行.然后我在桌子上做了一个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'
Run Code Online (Sandbox Code Playgroud)

因此,它似乎是在表上进行顺序扫描,即使只有大约一半的行具有此标志.索引被忽略了.

如果我做:

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)'
Run Code Online (Sandbox Code Playgroud)

所以无论如何,这个索引都没有被使用.

Mik*_*sen 4

我已经确认该索引按预期工作。

我重新创建了随机数据,只是这次设置diet_glutenfreerandom() > 0.9,因此只有 10% 的机会出现on

然后我重新创建索引并再次尝试查询。

SELECT RecipeId from RecipeMetadata where diet_glutenfree;
Run Code Online (Sandbox Code Playgroud)

返回:

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

和:

SELECT RecipeId from RecipeMetadata where NOT diet_glutenfree;
Run Code Online (Sandbox Code Playgroud)

返回:

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

看来我的第一次尝试被污染了,因为 PG 估计如果无论如何都必须加载一半以上的行,扫描整个表比命中索引更快。

但是,我认为我会在该列的完整索引上获得这些准确的结果。有没有办法验证部分索引中索引的行数?

更新

指数在40k左右。我创建了同一列的完整索引,它超过 200k,所以看起来它肯定是部分的。