来自虚拟表的记录顺序不正确

时间:2012-09-13 10:42:02

标签: sqlite virtual

在测试我们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 Virtual Table支持中的错误还是错过了某些内容?

2 个答案:

答案 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