【问题标题】:Multi-column indexes and ORDER BY多列索引和 ORDER BY
【发布时间】:2018-08-27 06:00:39
【问题描述】:

PostgreSQLdocumentation 指出,如果我们对索引为 ... (x ASC, y ASC) 的表运行查询 ... ORDER BY x ASC, y DESC,则无法使用索引,因为方向不匹配。

  1. 这是否意味着这个索引完全没用,或者数据库引擎可以使用索引对x ASC部分进行排序(然后手动对y DESC部分进行排序)?
  2. 如果我们运行查询... WHERE x = 999 ORDER BY y DESC,可以使用这个索引吗?

【问题讨论】:

  • 我不知道这个问题的答案,我猜至少在其中一种情况下是肯定的,但是您可以随时检查您的查询计划以了解发生了什么。如果您看到 Postgres 使用索引的最左侧部分,那么它正在被使用。
  • 从未尝试过,但为什么要首先创建组合索引?最好创建两个索引
  • 请注意,“方向”不匹配仅适用于多列索引。单列索引可用于双向排序

标签: postgresql indexing sql-order-by


【解决方案1】:

回答问题 1。

Postgres 12 或以上

,无法使用索引,如手册所示。您可以通过在任何表上创建这样的索引来进行验证,然后仅针对测试会话:

SET enable_seqscan = OFF;

然后:

EXPLAIN
SELECT * FROM tbl ORDER BY ORDER BY x, y DESC;

现在,如果索引可以以任何方式使用,那就可以了。但您仍会看到顺序扫描。

极端情况例外:如果index-only scan 是可能的,那么如果它远小于表,则可能仍会使用该索引。但是行必须从头开始排序。

相关:

Postgres 13 或更新版本

Postgres 13 添加了“增量排序”,可以通过 GUC 设置enable_incremental_sort 进行控制,默认为onThe release notes:

如果已知中间查询结果按一个或多个排序 所需排序顺序的前导键,附加排序可以 如果行被排序,则只考虑剩余的键 具有相同前导键的批次。

版本 13.1 和 13.2 已修复角落问题。所以 - 一如既往 - 一定要运行最新的单点版本。

现在,可以使用索引了。您会在EXPLAIN 计划中看到类似的内容:

Sort Key: x, y DESC
Presorted Key: x

它不如具有匹配(切换)排序顺序的索引高效,因为可以直接从索引中读取易于排序的行(根本不需要排序步骤)。但这可能是一个巨大的改进,特别是对于一个小的LIMIT,Postgres 必须对所有行进行历史排序。现在它可以查看每个(组)前导列,只对那些列进行排序,并在满足LIMIT 时立即停止。

回答问题 2。

是的,索引非常适合。

(即使索引有y ASC 也可以工作。它可以向后扫描。在这种情况下,只有NULL 放置是一个缺点。)

当然,如果x = 999 是一个稳定的谓词(我们感兴趣的始终是999)并且不止几行有不同的x,那么partial index 的效率会更高:

CREATE INDEX ON tbl (y DESC) WHERE x = 999;

dbfiddle here - Postgres 10

dbfiddle here - Postgres 13(第二个演示现在使用增量排序)

【讨论】:

  • 感谢 Erwin 的精彩回答!请注意:PG13 使用索引 SELECT * FROM tbl ORDER BY x, y DESC;也。至少在 dbfiddle 中。
  • @AntonBessonov:感谢您的指出!我添加了 Postgres 13 的升级细节。
猜你喜欢
  • 2021-07-06
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 2012-08-28
相关资源
最近更新 更多