postgresql - 可空列上的 Postgres 部分索引与常规/完整索引

标签 postgresql indexing null partial-index

我有一个包含 1m 条记录的表,其中 100k 条记录在 colA 上为空。剩余记录具有截然不同的值,在此列上创建常规索引与使用 where colA is not null 的部分索引有区别吗?

由于常规 Postgres 索引不存储 NULL 值,这与使用 where colA is not null 创建部分索引不一样吗?
这两个索引有什么优缺点吗?

最佳答案

如果您创建不带空值的部分索引,它不会使用它来查找空值。

这是一个在 13.5 上使用完整索引的测试。

# create index idx_test_num on test(num);
CREATE INDEX

# explain select count(*) from test where num is null;
                                     QUERY PLAN                                      
-------------------------------------------------------------------------------------
 Aggregate  (cost=5135.00..5135.01 rows=1 width=8)
   ->  Bitmap Heap Scan on test  (cost=63.05..5121.25 rows=5500 width=0)
         Recheck Cond: (num IS NULL)
         ->  Bitmap Index Scan on idx_test_num  (cost=0.00..61.68 rows=5500 width=0)
               Index Cond: (num IS NULL)
(5 rows)

并带有部分索引。

# create index idx_test_num on test(num) where num is not null;
CREATE INDEX

# explain select count(*) from test where num is null;
                                      QUERY PLAN                                      
--------------------------------------------------------------------------------------
 Finalize Aggregate  (cost=10458.12..10458.13 rows=1 width=8)
   ->  Gather  (cost=10457.90..10458.11 rows=2 width=8)
         Workers Planned: 2
         ->  Partial Aggregate  (cost=9457.90..9457.91 rows=1 width=8)
               ->  Parallel Seq Scan on test  (cost=0.00..9352.33 rows=42228 width=0)
                     Filter: (num IS NULL)
(6 rows)

Since regular postgres indexes do not store NULL values...

自 16 年前的 8.2 版 [检查笔记] 以来,情况并非如此。 8.2 docs说...

Indexes are not used for IS NULL clauses by default. The best way to use indexes in such cases is to create a partial index using an IS NULL predicate.

8.3 introduced nulls firstnulls last 以及围绕空值的许多其他改进,包括...

Allow col IS NULL to use an index (Teodor)

关于postgresql - 可空列上的 Postgres 部分索引与常规/完整索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71199741/

相关文章:

java - 将参数设置为持久值

sql - 在 postgreSQL 中索引和查询高维数据

php - Symfony Doctrine 和存储过程

python - for 循环和遍历列表

javascript - 将列索引转换为对应的列字母

java - 为什么 getSupportFragmentManager().findFragmentByTag(tag) 总是显示 null 值?

sql - PostgreSQL:使用窗口函数返回单行

postgresql - 如何替换列中的字符串,该字符串是另一个表中的外键

sqlite - SQLite 中的主键是否需要索引?

c - 我是否在 c 中访问了错误的(超出范围的)char 数组索引