在sqlite中,我尝试使用 IN
在我的 WHERE
子句,然后 ORDER BY
. 中使用的列 IN
以及 ORDER BY
都在索引中,与中使用的列在一起 IN
排名第一。但是,最终会使用临时树对 ORDER BY
,我本以为会使用索引。从我对sqlite查询优化器概述的阅读来看,我认为优化器应该将索引用于 IN
以及 ORDER BY
.
更具体地说,我有一个数据库表,用于存储机器学习训练数据集的元数据。这张table大约有7000万行。每一行都有一个带有随机整数(0-9)的列,以便轻松地将数据集分成10%的块(用于训练、测试等)。每一行也有一列,以允许预洗牌随机顺序(使用uuid)。然后,索引是数据集拆分编号上的多列索引,后跟随机顺序uuid。
在具有多个值的中(意外的索引用法):
所需查询的简化示例如下所示:
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5)
ORDER BY "t1"."random_order_uuid";
执行 EXPLAIN QUERY PLAN
这表明索引是用来获得正确的 dataset_split
s、 然后,使用临时树在 random_order_uuid
. 我本以为会使用索引而不是临时树。
单值等于(预期索引用法):
如果我想得到一个 dataset_split
使用等号。。。
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4
ORDER BY "t1"."random_order_uuid";
然后索引用于 dataset_split
选择和 random_order_uuid
根据需要。
在具有单个值的中(意外的索引用法):
使用单个 dataset_split
带着一个 IN
...
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4)
ORDER BY "t1"."random_order_uuid";
索引再次仅用于 dataset_split
选择和 random_order_uuid
在临时树上排序。
具有多个值的等于(意外的索引用法):
如果在上使用多个等式 dataset_split
分隔符 OR
s、 。。。
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4 OR "t1"."dataset_split" = 5
ORDER BY "t1"."random_order_uuid";
那么索引只用于 dataset_split
选择和排序是通过一个临时树来完成的。值得注意的是,优化器概述指出,多个等式由 OR
s将转换为 IN
由优化器,这再次表明 IN
结合 ORDER BY
这就是问题所在。
在具有多个不带order by的值的情况下(预期的索引用法):
如果 ORDER BY
省略。。。
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5);
索引用于 dataset_split
选择。
是否有什么原因我不知道为什么索引没有被用于查询的两个部分 IN
以及 ORDER BY
一起?我是否对优化如何在索引上工作做出了错误的假设?或者也许我在设置索引/查询时做错了什么?
使用sqlite 3.31.1检查
1条答案
按热度按时间rhfm7lfc1#
索引就像一个电话簿——或者任何其他有序的列表,如果这个引用已经过时了。
如果你选择两个姓,比如“史密斯”和“李”,那么名字是按字母顺序排列的。然而,没有一种简单的方法可以将名字组合起来,按名字排序——扎卡里·李在阿比盖尔·史密斯之前。只需附加它们就可以得到两个部分排序的列表。
这就是现在发生的事情
IN
. 对于索引扫描,排序信息是不准确的,因此大多数数据库只是将排序放入排序中。有一种称为skip-scan的机制(我认为oracle是唯一实现它的数据库,但如果我错了,我无疑会得到纠正)在某些情况下允许只进行索引优化。不过,老实说,我甚至不知道甲骨文会不会在这种情况下使用它。