考虑具有以下 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/