SQL-索引未同时用于IN和ORDER BY?

SQL-索引未同时用于IN和ORDER BY?,sql,sqlite,indexing,Sql,Sqlite,Indexing,在SQLite中,我尝试在我的WHERE子句中使用In进行过滤,然后使用orderby。在中的中使用的列和在中的顺序中使用的列都在索引中,在中的中使用的列位于索引的第一位。然而,一个临时树最终被用来按对顺序进行排序,我本以为会使用索引。从我对的阅读中,我认为优化器应该为中的和的顺序使用索引 更具体地说,我有一个数据库表,用于存储机器学习培训数据集的元数据。该表约有7000万行。每行有一列,其中包含一个随机整数(0-9),以便将数据集轻松拆分为10%的数据块(用于培训、测试等)。每行还具有一列,以

在SQLite中,我尝试在我的
WHERE
子句中使用
In
进行过滤,然后使用
orderby
。在中的
中使用的列和在
中的
顺序中使用的列都在索引中,在
中的
中使用的列位于索引的第一位。然而,一个临时树最终被用来按
顺序进行排序,我本以为会使用索引。从我对的阅读中,我认为优化器应该为
中的
的顺序使用索引

更具体地说,我有一个数据库表,用于存储机器学习培训数据集的元数据。该表约有7000万行。每行有一列,其中包含一个随机整数(0-9),以便将数据集轻松拆分为10%的数据块(用于培训、测试等)。每行还具有一列,以允许预洗牌随机顺序(使用UUID)。然后,该索引是数据集拆分编号上的多列索引,后跟随机顺序UUID

In具有多个值(意外的索引用法):

所需查询的简化示例如下所示:

SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5)
ORDER BY "t1"."random_order_uuid";
对此执行
EXPLAIN查询计划
会发现索引用于获取正确的
dataset\u split
s,但随后使用临时树对
random\u uuid进行排序。我本以为会使用索引而不是临时树


等于单个值(预期索引使用):

相反,如果我尝试使用equals获取单个
数据集\u split

SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4
ORDER BY "t1"."random_order_uuid";
然后,该索引将根据需要用于
dataset\u split
选择和
random\u order\u uuid


使用单个值(意外的索引用法):

使用单个
数据集\u拆分
,并在
中使用

SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4)
ORDER BY "t1"."random_order_uuid";
索引再次仅用于
数据集分割
选择,而
随机顺序
在临时树上排序


等于多个值(意外的索引用法):

如果在
数据集上使用多个相等项,则用
分隔

SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4 OR "t1"."dataset_split" = 5
ORDER BY "t1"."random_order_uuid";
然后,索引仅用于
数据集_split
选择,并使用临时树进行排序。值得注意的是,优化器会将由
s分隔的多个等式转换为
IN
,这再次表明
IN
ORDER by
组合是问题所在


In,具有多个不带排序依据的值(预期索引用法):

如果省略了“订购依据”

SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5);
该索引用于
数据集分割
选择


是否有什么原因我不知道为什么索引没有同时使用
中的
按顺序
用于查询的两个部分?我是否对优化如何在索引上工作做出了错误的假设?或者也许我在设置索引/查询时做错了什么


使用SQLite 3.31.1进行检查,索引就像电话簿一样,如果引用已过期,也可以是任何其他有序列表

如果选择两个姓氏,如“史密斯”和“李”,则姓氏按字母顺序排列。然而,没有一种简单的方法可以将名字组合起来,按名字排序——扎卡里·李在阿比盖尔·史密斯之前。只需添加它们,就可以得到两个部分排序的列表

这就是
中的
所发生的情况。对于索引扫描,排序信息是不准确的,因此大多数数据库只是对排序进行排序


有一种称为skip scan的机制(我认为Oracle是唯一实现它的数据库,但如果我错了,我无疑会得到纠正),在某些情况下,它可以允许只进行索引优化。不过,老实说,我甚至不知道Oracle是否会在这种情况下使用它。

好的,SQLite处理索引的方式与大多数数据库完全一样。“有什么问题吗?”戈登林诺夫,很抱歉我的问题不够清楚。根据我对SQLite优化器概述的阅读,我希望一个包含
IN
ORDER BY
列的索引将用于这两个列(如果这是所有包含的查询)。然而,事实似乎并非如此,我希望找出原因。无论是因为我犯了一些错误(很可能是),还是其他原因。我也不是说这种情况只发生在SQLite上,它只是我测试过的唯一一个数据库。@gomschenk。对于通常使用的索引的下一个键,比较需要
=
(跳过扫描有一个例外,但即使是按第二个键排序也不起作用)。@golmschenk。索引可以部分使用。它不必覆盖整个
,其中
。但基本规则是,当上一个键具有相等条件时,可以使用下一个键。注释中的
其中
可以使用
(a,d,b)
(a,d,c)
来缩小被访问的行数(可以分别添加第四个键,
c
d
,以便在不访问实际数据的情况下访问该值)。Sqlite可以进行跳过扫描(虽然我不知道在这种情况下是否会)如果索引已经被分析:@Shawn…谢谢你的指针。我不知道。