ORDER BY #除了简单地找到查询要返回的行之外,索引还可能能够以某种特定排序顺序交付这些行。这使得查询中的ORDER BY要求无需额外排序步骤即可满足。在PostgreSQL当前支持的索引类型中,只有 B-tree 能产生有序输出,其他索引类型返回匹配行的顺序则未指定,并且依赖具体实现。
规划器在满足ORDER BY要求时,会考虑两种方案:扫描一个与该要求匹配的可用索引,或者按物理顺序扫描表再显式排序。对于需要扫描表中很大一部分内容的查询,显式排序通常会比使用索引更快,因为它遵循顺序访问模式,需要的磁盘 I/O 更少。只有在只需取出少量行时,索引才更有价值。一个重要的特例是ORDER BY与LIMIT 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 FIRST是ORDER BY DESC的默认行为)。
你可以在创建 B-树索引时通过指定ASC、DESC、NULLS FIRST和/或NULLS LAST选项来调整索引的排序方式,例如:
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),就可以做到。
显然,具有非默认排序方式的索引是一项相当专门的特性,但在某些查询上它们有时能带来巨大的加速。是否值得维护这样的索引,取决于你需要这种特殊排序的查询出现得有多频繁。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。