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

时间:2015-11-04 15:36:16

标签: sql select optimization h2

注意:表/列/索引名称已组成。

背景

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

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

CREATE INDEX ab ON a(b);

问题

当我在没有过滤FK的情况下运行查询时:

EXPLAIN SELECT * FROM a ORDER BY b;

数据库正确使用索引进行排序。我知道这一点,因为此查询的结果(截断)返回:

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专家,但我很惊讶得到这些结果。也许我只需要以不同的方式查询这些信息,但我认为这是一个相对简单的案例。

1 个答案:

答案 0 :(得分:3)

事实证明答案很简单,虽然不是很明显(至少不是我)。该表需要在FK和订单列之间具有复合索引:

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 */