11.4. 索引和 ORDER BY

除了简单地查找要由查询返回的行外,索引还可以按特定的排序 Sequences 传递它们。这允许查询的ORDER BY规范而无需单独的排序步骤。在 PostgreSQL 当前支持的索引类型中,只有 B 树可以产生排序后的输出-其他索引类型以未指定的,依赖于实现的 Sequences 返回匹配的行。

计划者将考虑通过扫描与规范匹配的可用索引,或通过按物理 Sequences 扫描表并进行明确排序来满足ORDER BY规范。对于需要扫描表的大部分内容的查询,显式排序可能比使用索引更快,因为由于遵循 Sequences 访问模式,它需要较少的磁盘 I/O。当只需要获取几行时,索引会更有用。一个重要的特殊情况是ORDER BYLIMIT * n 结合使用:显式排序将必须处理所有数据以识别前 n 行,但是如果存在与ORDER BY匹配的索引,则前 n *行可以直接检索,而无需扫描其余部分。

缺省情况下,B 树索引以升序存储其条目,最后为空。这意味着对列x上的索引进行前向扫描会产生满足ORDER BY x(或更详细地说是ORDER BY x ASC NULLS LAST)的输出。索引也可以向后扫描,产生满足ORDER BY x DESC的输出(或更详细地说,ORDER BY x DESC NULLS FIRST,因为NULLS FIRSTORDER BY DESC的默认值)。

创建索引时,可以通过包括选项ASCDESCNULLS FIRST和/或NULLS LAST来调整 B 树索引的 Sequences;例如:

CREATE INDEX test2_info_nulls_low ON test2 (info NULLS FIRST);
CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST);

索引按升序存储(首先为空)可以满足ORDER BY x ASC NULLS FIRSTORDER BY x DESC NULLS LAST,具体取决于扫描的方向。

您可能想知道为什么当两个选项以及向后扫描的可能性将涵盖ORDER BY的所有变体时,为什么不麻烦同时提供全部四个选项。在单列索引中,这些选项确实是多余的,但在多列索引中,它们可能很有用。考虑(x, y)上的两列索引:如果向前扫描,则可以满足ORDER BY x, y;如果向后扫描,则可以满足ORDER BY x DESC, y DESC。但是可能是应用程序经常需要使用ORDER BY x ASC, y DESC。无法从纯索引中获得该 Sequences,但是如果将索引定义为(x ASC, y DESC)(x DESC, y ASC)是可能的。

显然,具有非默认排序 Sequences 的索引是一项相当专业的功能,但有时它们可以为某些查询带来巨大的提速。维护这样的索引是否值得取决于您使用需要特殊排序 Sequences 的查询的频率。