除了简单地查找要由查询返回的行之外,索引还可能能够以特定的排序顺序交付这些行。这使得查询的 ORDER BY 规范可以在不进行单独排序步骤的情况下得到满足。

在 PostgreSQL 当前支持的索引类型中,只有 B-tree 索引可以产生排序输出——其他索引类型返回匹配的行时顺序是未指定的,依赖于实现细节。

查询规划器会考虑通过扫描符合规范的可用索引或按物理顺序扫描表并进行显式排序来满足 ORDER BY 规范。对于需要扫描表中很大一部分数据的查询,显式排序可能比使用索引更快,因为顺序访问模式减少了磁盘 I/O。索引在只需要获取少数几行时更有用

一个重要特殊情况是 ORDER BYLIMIT n 结合使用:显式排序需要处理所有数据以识别前 n 行,但如果有一个与 ORDER BY 匹配的索引,可以直接检索前 n 行,而无需扫描其余部分。

默认情况下,B-tree 索引以升序存储条目,空值放在最后(表的 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-tree 索引的排序顺序;例如:

1
2
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),则是可能的。

显然,具有非默认排序顺序的索引是一个相当专业的功能,但在某些查询中有时可以显著提高速度。是否值得维护这样的索引取决于你使用需要特殊排序顺序的查询的频率。

相关链接

PostgreSQL: Documentation: 16: 11.4. Indexes and ORDER BY

OB tags

#PostgreSQL