Skip to content

11.4. 索引和ORDER BY#

除了查找查询返回的行之外,索引还能够以特定的排序顺序提供这些行。这允许查询的ORDER BY规范在没有单独排序步骤的情况下得到满足。在PostgreSQL当前支持的索引类型中,只有 B 树可以生成排序输出 — 其他索引类型以未指定的、与实现相关的顺序返回匹配行。

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

默认情况下,B 树索引按升序存储其条目,空值排在最后(表 TID 被视为条目相等时的决胜列)。这意味着对列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 树索引的排序;例如

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。无法从普通索引中获取该排序,但如果将索引定义为(x ASC, y DESC)(x DESC, y ASC),则可以获取。

显然,具有非默认排序顺序的索引是一项相当专门的功能,但有时它们可以极大地提高某些查询的速度。是否值得维护此类索引取决于您使用需要特殊排序顺序的查询的频率。