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 FIRST
默认是ORDER 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)
就是可能的了。
明显的,没有默认排序顺序的索引是比较专业的特征,但是有时它们对特定的查询可以产生极大的加速。 是否值得维持这样的索引取决于你使用需要特殊排序顺序的查询的频率。