sqlite - 虚拟表中的记录顺序不正确

标签 sqlite virtual

在测试我们的 SQLite Virtual Table 实现期间我们遇到了意外行为的机制。
对于以下 virtual table结构体:

create table X(ID int, RL real)

此查询按 RL 以正确的降序返回所有记录
field 。

查询 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 中的错误吗?支持还是我们错过了什么?

最佳答案

正如 allocateIndexInfo() 中的评论说,只有当“ORDER BY 子句仅包含当前虚拟表中的列”时,您的虚拟表才有机会实现排序。在您的查询中,排序列来自的虚拟表仅用于查找 ID 列,并且此类单值查找不能用于排序。

使用 SQLite 3.7.14,我在查询 2 的计划中确实得到了“USE TEMP B-TREE FOR ORDER BY”。您的 xBestIndex 返回的值是什么?

关于sqlite - 虚拟表中的记录顺序不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12404446/

相关文章:

C++调用子类的虚方法而不是基类

c# - 在覆盖属性的 Getter 中调用 "Base-Getter"

c++ - 我想我已经重写了一个虚拟方法,但我仍然得到 : "X must implement the inherited pure virtual method Y"

c# - 如何下载azure虚拟网络的客户端vpn exe文件

android - 创建 SQLite 数据库来存储地理点并将其读取到 MapActivity 上

ruby-on-rails - 带有 sqlite 的 rails 中的 boolean 值

java - resultSet.next() 返回 false,即使表已填充

java - 在 Java 中创建虚拟模板方法

java - Android - 在 TableLayout 中显示 SQLite 数据库记录

Android 错误 - close() 从未在数据库上显式调用