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