Sim*_*tti 11 postgresql index postgresql-8.3 postgresql-9.1
我有一个名为auto_review
where column type is的数据库列boolean
。该字段有一个索引,使用 ActiveRecord ORM 创建。
CREATE INDEX index_table_on_auto_renew ON table USING btree (auto_renew);
Run Code Online (Sandbox Code Playgroud)
当我查询布尔值的字段时,PG 按预期使用索引。
EXPLAIN for: SELECT "table".* FROM "table" WHERE "table"."auto_renew" = 'f'
QUERY PLAN
----------------------------------------------------------------------------------------------
Bitmap Heap Scan on table (cost=51.65..826.50 rows=28039 width=186)
Filter: (NOT auto_renew)
-> Bitmap Index Scan on index_domains_on_auto_renew (cost=0.00..44.64 rows=2185 width=0)
Index Cond: (auto_renew = false)
(4 rows)
Run Code Online (Sandbox Code Playgroud)
当值为 时NULL
,使用顺序扫描。
EXPLAIN for: SELECT "table".* FROM "table" WHERE "table"."auto_renew" IS NULL
QUERY PLAN
----------------------------------------------------------------
Seq Scan on table (cost=0.00..1094.01 rows=25854 width=186)
Filter: (auto_renew IS NULL)
(2 rows)
Run Code Online (Sandbox Code Playgroud)
我很想知道这个选择背后的原因。
Erw*_*ter 20
通常,col IS NULL
是(默认)b 树索引搜索的可能候选者。手册:
此外,索引列上的
IS NULL
或IS NOT NULL
条件可以与 B 树索引一起使用。
要获得证据,请禁用顺序扫描(仅在测试会话中!):
SET enable_seqscan = OFF;
Run Code Online (Sandbox Code Playgroud)
enable_seqscan (boolean)
启用或禁用查询计划程序对顺序扫描计划类型的使用。完全抑制顺序扫描是不可能的,但是如果有其他方法可用,关闭此变量会阻止计划者使用一种方法。默认为开启。
然后再试一次:
EXPLAIN ANALYZE SELECT * FROM tbl WHERE auto_renew IS NULL;
Run Code Online (Sandbox Code Playgroud)
这可能会导致位图索引扫描变慢比表上的顺序扫描。
重置或关闭会话(设置为会话本地)。
RESET enable_seqscan;
Run Code Online (Sandbox Code Playgroud)
boolean
列上的索引仅在某些情况下有用。规划器仅在期望更快时才使用索引。计算基于您的成本设置和收集的统计数据ANALYZE
。如果表中有相当大的部分符合您的条件(大约 5% 或更多,这取决于),通常进行全表扫描会更快。
这使得列中的稀有值boolean
成为普通索引的唯一有用候选者。并且为此创建(更专业的)部分索引通常更有效- 如果查询条件匹配,维护成本更低,更小,更快并且更容易使用。
如果您有很多查询查找行,auto_renew IS NULL
并且这种NULL
情况不是很常见(和/或您需要某种排序顺序),那么此索引将有助于快速查找/排序这些行:
CREATE INDEX index_tbl_tbl_id_auto_renew_null ON tbl (tbl_id)
WHERE auto_renew IS NULL;
Run Code Online (Sandbox Code Playgroud)
部分索引的条件必须在WHERE
查询的子句中或多或少准确地重复,以使查询规划器意识到索引是适用的。
索引列 ( tbl_id
) 是任意选择。重要的部分是WHERE
条款。此特定索引对于带有ORDER BY tbl_id
或附加过滤器或连接的查询最有效tbl_id
。您可以将其设为多列索引。布尔列与其他列结合使用时通常更有用。
旁白:ORM 是经常无法从 RDBMS 中充分发挥潜力的拐杖。
归档时间: |
|
查看次数: |
3871 次 |
最近记录: |