对WHERE和ORDER BY使用sqlite索引

时间:2013-12-12 02:12:02

标签: sqlite

我有一个看起来像这样的表:

CREATE TABLE foo (type integer, priority integer);

'type'是少数值之一。

我想进行查询以选择按优先级排序的某种类型的样本行:

SELECT * FROM foo WHERE type = 0 ORDER BY priority DESC LIMIT 100;

我正在尝试创建一个索引以使其快速。但似乎sqlite不允许我处理以下两种情况:

  1. foo中的大多数项都有type = 0.在这种情况下,我们应该使用索引查找优先级最高的项,然后检查哪些项的type = 0.
  2. foo中的大多数项都有类型!= 0.在这种情况下,我们应该使用类型索引来查找类型为0的项,然后对它们进行排序。
  3. 我可以让sqlite使用其中任何一个,但我无法弄清楚是否有可能有一个单一的索引/查询对两种情况都有效。似乎(类型,优先级)上的索引可以工作,但看起来sqlite只用于第一次查找而不是ORDER BY。

1 个答案:

答案 0 :(得分:1)

两列上的单个索引允许使用在两种情况下都有效的执行计划:

> CREATE INDEX t_p ON foo(type, priority);
> EXPLAIN QUERY PLAN SELECT * FROM foo WHERE type = 0 ORDER BY priority DESC LIMIT 100;
0|0|0|SEARCH TABLE foo USING COVERING INDEX t_p (type=?)
> .explain on
> EXPLAIN SELECT * FROM foo WHERE type = 0 ORDER BY priority DESC LIMIT 100;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Trace          0     0     0                    00
1     Noop           0     0     0                    00
2     Integer        100   1     0                    00
3     Goto           0     15    0                    00
4     OpenRead       2     3     0     k(3,B,B,B)     00
5     Integer        0     2     0                    00
6     SeekLe         2     13    2     1              00
7       IdxLT          2     13    2     1              00
8       Column         2     0     4                    00
9       Column         2     1     5                    00
10      ResultRow      4     2     0                    00
11      IfZero         1     13    -1                   00
12    Prev           2     7     0                    00
13    Close          2     0     0                    00
14    Halt           0     0     0                    00
15    Transaction    0     0     0                    00
16    VerifyCookie   0     2     0                    00
17    TableLock      0     2     0     foo            00
18    Goto           0     4     0                    00

首先,SQLite打开索引并快速搜索type列小于或等于零(6 SeekLe)的最后一条记录。 然后它返回索引的结果,向后(12 Prev),直到遇到type列小于零(7 IdxLT)的索引条目。

这是对索引的单次扫描,永远不需要跳过不需要的条目。