PostgreSQL 可以在其索引中使用空值吗?

Fur*_*der 10 postgresql index index-tuning postgresql-9.1

我一直在读这本书,它说

数据库假定 Indexed_Col IS NOT NULL 覆盖的范围太大而无用,因此数据库不会从这种情况驱动到索引。

我承认这本书已经有 10 多年的历史了,但它已经证明了 非常有用——使用从书中收集的说明,我已经将查询速度提高了 10 倍。

此外,在运行EXPLAIN ANALYZESELECT查询,我发现没有我的指标正在使用,所有的权利,即使他们应该是。

因此,我的问题是:

假设有一个表,它有一个列,其列定义包括“NOT NULL”,并且存在一个覆盖该列的索引,该索引是否会用于该表的查询,其中该列是查询的一部分?

喜欢:

CREATE TABLE my_table(
a varchar NOT NULL
);

CREATE INDEX ix_my_table ON my_table(a);

SELECT a from my_table;
Run Code Online (Sandbox Code Playgroud)

Cra*_*ger 9

PostgreSQL 当然可以使用索引IS NOT NULL. 我也没有看到有关该条件的任何查询规划器假设。

如果列 ( pg_statistic.stanullfrac)的空分数足够低以表明索引对查询具有有用的选择性,则 PostgreSQL 将使用索引。

我不明白你想说什么:

如果这是正确的,我是否理解定义为“NOT NULL”的列上的索引不能在使用该列的查询中使用?

当然,索引不会用于IS NOT NULL条件NOT NULL列。它总是匹配 100% 的行,因此 seqscan 几乎总是要快得多。

如果索引没有过滤掉查询的大部分行,PostgreSQL 将不会使用索引。唯一可能的例外是当您请求单个索引覆盖的一组列时,其顺序与索引的顺序匹配。然后 PostgreSQL 可能会进行仅索引扫描。例如,如果有一个索引t(a, b, c)并且你:

select a, b FROM t ORDER BY a, b, c;
Run Code Online (Sandbox Code Playgroud)

PostgreSQL 可能会使用你的索引,即使没有行被过滤掉,因为它只需要读取索引并且可以跳过读取堆,避免进行排序等。

  • @FuriousFolder 嘿,这里有太多的否定。PostgreSQL 不会将“NOT NULL”列上的索引用于“IS NOT NULL”查询,除非该索引对“WHERE”子句的其他部分、连接过滤器等也有用,或者可用于有序索引- 仅扫描。换句话说,它会完全忽略“NOT NULL”列上多余的“IS NOT NULL”,并根据其他细节做出索引使用选择。(请参阅编辑,重新仅索引扫描)。 (2认同)