在测试我们SQLite Virtual Table
机制的实现时,我们遇到了意外的行为。
对于以下virtual table
结构:
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;
执行计划1 :
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)
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 t2.RL desc
执行计划2 :
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)
正如您所看到的,没有提到的索引可供排序。 对真实表执行的查询(具有与我们的虚拟表完全相同的结构)如下所示:
查询3 :
select * from Table1 t1 left outer join Table1 t2 on t1.ID = t2.ID order by t2.RL desc
执行计划3 :
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_index_orderby
结构(sqlite3_index_info
结构中的部分)收到的内容xBestIndex
时它们是否包含有关排序的任何信息。
此外,orderByConsumed
out参数返回False(因为我们的输出没有排序,我们假设sqlite本身会对行进行排序)。
这是SQLite Virtual Table
支持中的错误还是错过了某些内容?
答案 0 :(得分:2)
正如allocateIndexInfo()
中的注释所说,只有当“ORDER BY子句仅包含当前虚拟表中的列”时,您的虚拟表才有机会实现排序。在您的查询中,排序列来自的虚拟表仅用于查找ID列,并且单个值的查找不可用于排序。
使用SQLite 3.7.14,我的查询计划中得到“USE TEMP B-TREE FOR ORDER BY”。你的xBestIndex返回的值是什么?
答案 1 :(得分:2)
问题的原因在于orderByConsumed
输出标志值的处理不当。
对于JOIN
的此查询,我们的xBestIndex
实现返回orderByConsumed = True
以查找与ON
条件相匹配的索引,这实际上是不正确的,因为没有在那种情况。这忽略了任何进一步的ORDER BY
条款成员。
修复orderByConsumed
启动后仅对True
标志大于0的索引返回nOrderBy
,否则返回False
。