Sqlite 虚拟表中记录的顺序不正确
在测试Sqlite 虚拟表中记录的顺序不正确,sqlite,virtual,Sqlite,Virtual,在测试SQLite虚拟表机制的实现过程中,我们遇到了一个意外的行为。 对于以下虚拟表结构: create table X(ID int, RL real) 此查询按RL的正确降序返回所有记录 场 查询1: select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc; explain query plan select * from VTab t1 left outer join VTab
SQLite虚拟表
机制的实现过程中,我们遇到了一个意外的行为。
对于以下虚拟表
结构:
create table X(ID int, RL real)
此查询按RL的正确降序返回所有记录
场
查询1:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
执行计划1:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
D1
这里是由我们的xBestIndex
方法实现生成的值,表示按字段#1=RL降序排序。
C0=0
这里表示字段#0=ID的操作相等。
这正如预期的那样有效
但是,下一个查询返回的行(RL字段的别名不同)没有任何排序
查询2:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
执行计划2:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
正如您所看到的,没有提到要排序的索引。
针对实际表(与我们的虚拟表具有完全相同的结构)执行的查询如下所示:
查询3:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
执行计划3:
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t1.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0:D1; (~0 rows)
0|1|1| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from VTab t1 left outer join VTab t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE VTab AS t1 VIRTUAL TABLE INDEX 0: (~0 rows)
0|11| SCAN TABLE VTab AS t2 VIRTUAL TABLE INDEX 4:C0=0; (~0 rows)
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
explain query plan select * from Table1 t1 left outer join Table1t2 on t1.ID = t2.ID order by t2.RL desc;
0|0|0| SCAN TABLE Table1 AS t1 (~1000000 rows)
0|1|0| SEARCH TABLE Table1 AS t2 USING AUTOMATIC COVERING INDEX (ID=?)
0|1|0| (~7 rows)
0|0|0| USE TEMP B-TREE FOR ORDER BY
正如您所看到的,这里有使用B-tree的排序
我们检查了sqlite3\u index\u orderby
结构(sqlite3\u index\u info
结构的一部分)中的内容,这些结构在xBestIndex
中没有包含任何排序信息。
另外,orderbyconsumered
out参数返回False(因为我们的输出没有排序,我们假设它本身会对行排序)
这是SQLite虚拟表支持中的一个错误还是我们遗漏了什么?正如
allocateIndexInfo()
中的注释所述,只有在“ORDERBY子句仅包含当前虚拟表中的列”的情况下,虚拟表才有机会实现排序。在您的查询中,排序列所来自的虚拟表仅用于查找ID列,这种单个值的查找不可用于排序
使用SQLite 3.7.14,我在查询2的计划中得到了“使用TEMP B-TREE FOR ORDER BY”。xBestIndex返回的值是什么?问题的原因在于对
orderbyconsumered
输出标志值的处理不当
对于这个带有JOIN
的查询,我们的xBestIndex
实现返回了orderbyconsumered=True
的索引,该索引在条件下匹配,实际上是不正确的,因为在这种情况下没有进行排序。这忽略了
子句成员的任何进一步的命令
在修复后,orderbyconsumered
开始返回True
仅适用于nOrderBy
标志大于0的索引,否则返回False
。感谢您的回答。我在我的xBestIndex
实现中发现了一个bug。它意外地为其中一个索引返回了orderbyconsumered=True
,而根本不需要排序(对于符合条件的索引),SQLite引擎只是暗示我对我这边的所有东西都进行了排序。修复后,问题消失了。