SQLite:使用范围查询索引进行查询优化

时间:2015-03-20 07:22:58

标签: sql sqlite

以下是我真正问题的简化版本:表中有两列和一个索引。也就是说,

CREATE TABLE T (a integer primary key, b integer not null);
CREATE INDEX Ti on T (b, a);

列a是主键,因此唯一但列b可以有许多重复项。有问题的查询就像

SELECT * from T where b=5 and a>3 order by b, a limit 1;

我的期望是,只有一个二进制搜索应该足以找到满足条件的最小(b,a)对,如果它充分利用了索引。此外,the document on SQLite query planner明确指出

  

如果索引的初始列(列a,b等)出现在WHERE子句中,则可以使用索引。索引的初始列必须与=或IN或IS NULL运算符一起使用。 使用的最右列可以使用不等式。 对于使用的索引的最右列,最多可以有两个不等式必须将允许两个极端之间的列值。

但是explainexplain query plan的结果非常令人失望。 (sqlite3 3.8.8.3)

sqlite> explain query plan select * from T where b=5 and a>3 order by b,a limit 1;
0     0              0     SEARCH TABLE T USING COVERING INDEX Ti (b=?)

sqlite> explain select * from T where b=5 and a>3 order by b,a limit 1;
5     SeekGE         2     14    2     1              00               
6       IdxGT          2     14    2     1              00               
7       IdxRowid       2     3     0                    00               
8       Le             4     13    3                    54               
9       Copy           3     5     0                    00               
10      Column         2     0     6                    00               
11      ResultRow      5     2     0                    00               
12      IfZero         1     14    -1                   00               
13    Next           2     6     0                    00               

当然,它仅使用索引来定位b = 5的第一行,然后进行线性扫描以找到a> 3的行。当只有少量行具有重复的b值时,它可能没问题,但否则可能是一个问题。而不是p4 = 1的SeekGE,具有p4 = 2的SeekGT和具有p4 = 1的IdxGT可以更有效,因为它可以仅通过一次二分搜索直接定位右行。

所以问题是,当然,如果你说这就是它现在的方式,那么我可以做的并不多,但为了以防万一我还有什么缺少可以使其更好地工作? ANALYZE不是一个选项,因为这是一种通常更好的方法来处理范围查询,而不仅仅是在特定的数据集上。

0 个答案:

没有答案