对值为NULL的布尔值进行查询时发生意外的Seq扫描


10

我有一个称为auto_review列类型为的数据库列boolean。使用ActiveRecord ORM创建该字段的索引。

CREATE INDEX index_table_on_auto_renew ON table USING btree (auto_renew);

当我在字段中查询布尔值时,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)

当值为时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)

我很好奇知道这种选择的原因。

Answers:


19

通常,col IS NULL可能是(默认)b树索引搜索的候选对象。手册

同样,索引列上的IS NULLor IS NOT NULL条件可以与B树索引一起使用。

为了获得证明,请禁用顺序扫描(仅在测试会话中!):

SET enable_seqscan = OFF;

在这里引用手册

enable_seqscan (boolean)

启用或禁用查询计划程序对顺序扫描计划类型的使用。不可能完全抑制顺序扫描,但是如果有其他可用方法,则关闭此变量将阻止计划者使用一种。默认为开。

然后再试一次:

EXPLAIN ANALYZE SELECT * FROM tbl WHERE auto_renew IS NULL;

这可能会导致位图索引扫描比对表的顺序扫描

重置或关闭会话(该设置为本地会话)。

RESET enable_seqscan;

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;

必须在WHERE查询的子句中或多或少准确地重复部分索引的条件,以使查询计划者认识到该索引适用。

索引列(tbl_id)是任意选择。重要的部分是WHERE条款。对于使用ORDER BY tbl_id或附加过滤器或加入的查询,此特定索引最有效tbl_id。您可以将其设为多列索引。布尔列通常与其他列结合使用更为有用。

撇开:ORM是拐杖,经常无法充分发挥RDBMS的全部潜力。


辉煌的答案,谢谢欧文。真遗憾,我不能两次投票。
西蒙妮·卡列蒂
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.