sql - PostgreSQL:创建索引以快速区分 NULL 和非 NULL 值

标签 sql postgresql indexing null

考虑具有以下 WHERE 谓词的 SQL 查询:

...
WHERE name IS NOT NULL
...

其中 name 是 PostgreSQL 中的文本字段。

没有其他查询检查此值的任何文本属性,只是检查它是否为 NULL。因此,a full btree index似乎有点矫枉过正,尽管 it supports this distinction :

Also, an IS NULL or IS NOT NULL condition on an index column can be used with a B-tree index.

快速区分 NULL 和非 NULL 的正确 PostgreSQL 索引是什么?

最佳答案

我的解释是您声称它在两个方面“矫枉过正”:在复杂性(使用 B 树而不只是列表)和空间/性能方面。

对于复杂性,这并不过分。 B-Tree 索引更可取,因为从中删除 比某种“无序”索引更快(因为缺少更好的术语)。 (无序索引需要进行完整的索引扫描才能删除。)鉴于这一事实,无序索引的任何 yield 通常都会被损害所抵消,因此开发工作是不合理的。

但是,为了空间和性能,如果您想要一个高度选择性的索引以提高效率,您可以在索引上包含一个 WHERE 子句,如 fine manual 中所述:

CREATE INDEX ON my_table (name) WHERE name IS NOT NULL;

请注意,只有在执行查询时允许 PostgreSQL 忽略大量行时,您才会从该索引中受益。例如,如果 99% 的行具有 name IS NOT NULL,索引不会给您带来任何好处,而只是让全表扫描发生;事实上,它会降低效率(如 @CraigRinger 注释),因为它需要额外的磁盘读取。但是,如果只有 1% 的行具有 name IS NOT NULL,那么这代表着巨大的节省,因为 PostgreSQL 可以忽略您的查询的大部分表。如果您的表非常大,即使删除 50% 的行也是值得的。这是一个调整问题,索引是否有值(value)将在很大程度上取决于数据的大小和分布。

此外,如果您仍然需要为 name IS NULL 行创建另一个索引,那么在空间方面的 yield 将非常有限。参见 Craig Ringer's answer了解详情。

关于sql - PostgreSQL:创建索引以快速区分 NULL 和非 NULL 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31966218/

相关文章:

MongoDB 复合索引

ravendb - 转换结果

java - 如何获取有关 Arraylist 索引的整数值

sql - 使用当前连接从 sql 存储过程调用 dll 函数

postgresql - information_schema.columns 中的 ordinal_position 值乱序

sql - 使用WITH子句插入表在postgres中不起作用

postgresql - 应用程序容器未正确连接到部署中的 postgres 数据库

mysql - 为什么MySQL不使用最优索引

sql - 从文本 regexp_substr 中删除第二个引号

sql - 如何将 Oracle 时间戳值从当前更新为过去的时间戳