【问题标题】:Why is this query not using an index sort?为什么这个查询不使用索引排序?
【发布时间】:2015-11-05 01:49:12
【问题描述】:

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

背景

我在弄清楚如何有效地查询我的一个数据库表时遇到了一些麻烦(该表有大约一百万行)。有问题的查询涉及带有外键的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 专家,但我很惊讶得到这些结果。也许我只是需要以不同的方式查询这些信息,但我认为这是一个相对简单的案例。

【问题讨论】:

  • 不知道为什么这被否决并被投票关闭(因为离题!?)。我很想听听你的推理。也许是由于我对数据库的一些无知,但在来这里之前我做了相当多的研究和实验。
  • 您是否查看了估计的执行计划/解释查询?
  • @MarshallTigerus 是的,我将其结果作为问题的一部分发布(截断)。没有让我了解为什么我的索引没有被使用,只是没有。除非你指的是我使用 EXPLAIN ... 之外的其他东西
  • @Default 索引有助于减少磁盘访问时间,因为它们将数据库指向数据在硬盘驱动器上的位置。如果在应用 where 子句之后,结果被存储在内存中进行排序,那么索引就毫无用处了。我怀疑这就是您的第二个查询发生的情况。

标签: sql select optimization h2


【解决方案1】:

事实证明,答案很简单,虽然不是很明显(至少对我来说不是)。该表需要在 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 */    

【讨论】:

  • 这里最大的问题可能只是我不明白数据库只能利用一个索引。因此,当我对两列都有单独的索引时,它选择了最好的一个(仅 FK 索引),这就是导致索引排序不足的原因。通过在 order by 中包含 FK(尽管是多余的)来强制使用复合索引,允许数据库按所述索引进行过滤和排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 2011-08-24
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多