为什么这个查询不使用索引排序?

Why is this query not using an index sort?

注意: Table/Column/Index名字是编的。

背景

我在弄清楚如何有效地查询我的一个数据库 table 时遇到了一些麻烦(table 有大约一百万行)。有问题的查询涉及一个带有外键的 WHERE 子句和一个带有另一列的 ORDER BY 子句。

数据库在 FK 上生成索引,我在将用于排序的列上创建索引:

CREATE INDEX ab ON a(b);

问题

当我运行查询时FK没有过滤:

EXPLAIN SELECT * FROM a ORDER BY b;

数据库正确使用索引进行排序。我知道这一点是因为此查询 returns:

的结果 (t运行cated)
FROM PUBLIC.A
  /* PUBLIC.AB */
ORDER BY 3
/* index sorted */

但是,当查询被修改为在 FK 上进行过滤时:

EXPLAIN SELECT * FROM a WHERE a_fk_id = 3 ORDER BY b

只使用FK索引:

FROM PUBLIC.A
   /* PUBLIC.A_FK_INDEX_NAME: A_FK_ID = 3 */
WHERE A_FK_ID = 3
ORDER BY 3

如您所见,仅使用了 FK 索引。

问题

这是怎么回事?

我认为这可能与单独的索引有关,但甚至创建了一个多列索引,如:

CREATE INDEX a_fk_id_b ON a(a_fk_id, b);

没有采取任何措施来解决问题(也没有颠倒索引中这些列的顺序,但我没想到会这样)。

如有任何建议,我们将不胜感激。我绝不是数据库或 SQL 专家,但我很惊讶得到这些结果。也许我只是需要以不同的方式查询这些信息,但我认为这是一个相对简单的案例。

原来答案很简单,虽然不是很明显(至少对我来说不是)。 table FK 和 order 列之间需要有复合索引:

CREATE INDEX a_fk_id_b ON a(a_fk_id, b);

为了让数据库使用该索引而不是生成的 FK 索引,a_fk_id 列需要包含在 ORDER BY 子句中:

EXPLAIN SELECT * FROM a WHERE a_fk_id = 3 ORDER BY a_fk_id, b;

这导致我们的复合索引被用于过滤和排序,如这个截断的解释计划所示:

FROM PUBLIC.A
   /* PUBLIC.A_FK_ID_B: A_FK_ID = 3 */
WHERE A_FK_ID = 3
ORDER BY 25, 19
/* index sorted */