为什么 PostgreSQL 9.5 不使用我最新的 ORDER BY 索引,即使它使用类似的索引就好了?

Kev*_*Kev 7 postgresql performance index optimization postgresql-9.5 postgresql-performance

(这篇文章的后续内容:当我在子查询中 ORDER BY 时,为什么我的 PostgreSQL 表达式索引没有被使用?

PostgreSQL 9.5。

我不能透露全部细节,但table有 22 列和 5 个索引:

  1. 主键 ('pk'), text(btree)
  2. 另一个text(btree)
  3. 一个timestamp with time zone(btree)
  4. 一个tsvector(杜松子酒)
  5. 我最新的一个bigint(btree)

(从上一篇文章你知道我试图避免创建这个额外的列,只是使用表达式索引——将两integer列加在一起——没有成功。bigint这里的列可能只是“整数”,但我做了一个创建它时出错;添加列、填充它并重新编制索引花了大约一个小时,所以我希望这不相关,但要提及它以防万一。)

除了tsvector.

以下查询都只需要 12ms 并且只使用一个Index Scan

  1. SELECT pk FROM table ORDER BY pk DESC LIMIT 10
  2. SELECT pk FROM table ORDER BY text_column DESC LIMIT 10
  3. SELECT pk FROM table ORDER BY timestamp_column DESC LIMIT 10

但是,如果我尝试将我的新bigint索引用于ORDER BY

SELECT pk FROM table ORDER BY bigint_column DESC LIMIT 10

...它需要 2.7 秒并使用Limit -> Sort -> Seq Scan.

我的“作弊”方法是我似乎能够使用索引的最接近的方法:

SELECT pk
FROM table
WHERE bigint_column > 1000000
ORDER BY bigint_column DESC LIMIT 10
Run Code Online (Sandbox Code Playgroud)

这需要 12 毫秒并使用Limit -> Sort -> Bitmap Heap Scan (bigint_column > 1000000) -> Bitmap Index Scan (bigint_column > 1000000).

这是在VACUUM ANALYZE添加索引之后。

我觉得奇怪的是我的表达索引没有被用于另一个问题。现在它只是一个普通的旧专栏(我什至没有添加实际走这条路线的必要触发器。)

为什么我的最新索引没有被使用,而其他三个工作“很好”?(正如在https://dba.stackexchange.com/a/183290/28774的评论中指出的那样,仅索引扫描会更好。我不明白为什么所有这些查询都不会使用至少索引扫描,更不用说仅索引扫描,而不是完整的 Seq 扫描。)

索引定义具有DESC NULLS LAST(尽管它是不可为空的列。)

jja*_*nes 7

在 中PostgreSQLDESC NULLS LAST不能使用is 的索引来满足ORDER BYis DESC NULLS FIRST(包括排序,DESC因为这意味着NULLS FIRST)。即使将列定义为NOT NULL.

您可以重建索引,或者(因为您知道该列不为空)您可以添加NULLS LAST到您的查询中ORDER BY以使其与现有索引匹配。

请注意,PostgreSQL它知道如何向后跟踪索引,因此默认索引(隐式ASC NULLS LAST)也能够满足您的DESC NULLS FIRST查询。因此,在索引中指定 DESC 很少很重要,但指定 NULLS 排序的终点可能很重要。