11.4. 索引和ORDER BY

除了简单地找到被查询返回的行, 索引也能够在一个特定的排序中提供它们。 这使得查询的ORDER BY规范在没有一个单独的排序步骤下能够实现。 目前PostgreSQL支持的索引类型中,只有B-tree 能产生排序输出— 其他索引类型返回 未指定的匹配行,依赖于实现秩序。

规划器在通过扫描匹配规范的可用索引,或对表进行物理顺序扫描,做一个明确的 排序时会考虑满足ORDER BY规范。当对表进行的查询需要大范围扫描时,一个明确的排序很可能比使用索引要快。 因为对于顺序访问模式,它需要 减少磁盘I/O。当只有几行需要获取时,索引更有用。 一个重要的特殊情况是ORDER BY连接 LIMIT n:明确的排序将处理 所有的数据,以确定第一个n行,但如果有一个索引匹配ORDER BY, 第一个n行可以直接检索,没有扫描其余的。

缺省情况下,B-tree索引存储升序存放他们的记录(空记录在最前面)。 这意味着,向前索引扫描在列x产生满足ORDER BY x的输出(或更冗长,ORDER BY x ASC NULLS LAST)。 索引也可以向后扫描,产生满足ORDER BY x DESC产生输出(或更冗长,ORDER BY x DESC NULLS FIRST,因为 NULLS FIRSTORDER BY DESC的缺省)。

当创建索引时,你可以通过选项ASC, DESC, NULLS FIRST, 和(或者)NULLS LAST调整B-tree索引的排序,比如:

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 FIRST还是ORDER 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),那么就可能得到该排序。

显然,非缺省排序的索引是一个相当专业的功能,但有时却可以提高某些查询的速度。 是否值得维护这样一个索引取决于你经常使用需要一个特殊排序的查询。