sql-index不同时用于in和order by?

piah890a  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(229)

在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检查

rhfm7lfc

rhfm7lfc1#

索引就像一个电话簿——或者任何其他有序的列表,如果这个引用已经过时了。
如果你选择两个姓,比如“史密斯”和“李”,那么名字是按字母顺序排列的。然而,没有一种简单的方法可以将名字组合起来,按名字排序——扎卡里·李在阿比盖尔·史密斯之前。只需附加它们就可以得到两个部分排序的列表。
这就是现在发生的事情 IN . 对于索引扫描,排序信息是不准确的,因此大多数数据库只是将排序放入排序中。
有一种称为skip-scan的机制(我认为oracle是唯一实现它的数据库,但如果我错了,我无疑会得到纠正)在某些情况下允许只进行索引优化。不过,老实说,我甚至不知道甲骨文会不会在这种情况下使用它。

相关问题