帮助我优化我的sqlite查询
表格:
CREATE TABLE links (
c INTEGER NOT NULL,
position INTEGER NOT NULL,
key_id INTEGER REFERENCES keys(id),
PRIMARY KEY(c, position, key_id)
) WITHOUT ROWID;
查询
select c_1.* from links c_1
join links c_2 on c_1.key_id = c_2.key_id and c_2.position > c_1.position
join links c_3 on c_1.key_id = c_3.key_id and c_3.position > c_2.position
join links c_4 on c_1.key_id = c_4.key_id and c_4.position > c_3.position
where c_1.c = unicode('A')
and c_2.c = unicode('p')
and c_3.c = unicode('i')
and c_4.c = unicode('x')
这个想法是通过索引一个单词('key_id')的每个稍后('c')来实现子字符串搜索。我试图回答以下要求:给我所有包含A
且位置大于p
且具有A
且位置大于i
并且相同的单词用p
和i
。上面的查询应与以下单词匹配:
换句话说,我正在尝试优化以下查询:
x
查询计划如下所示:select * from links where key like '%A%p%i%x%'
样本结果
在此示例中,它找到了三个键。稍后,我将其映射到单词,并能够显示它找到的前缀是什么。
c|position|key_id
-----------------
65 1 121
65 1 2292
65 1 3919
65 1 3923
65 1 3925
65 1 3933
65 1 3946
65 1 4375
65 1 4375
65 1 4375
65 1 4375
中有240,076行的时间,执行需要2秒。如何使其运行更快?
您的主键索引在links
上,但是在您的查询中,您的c, position, key_id
和WHERE
测试将ON
等同,将c
等同,并将position
等同。这意味着索引中的key_id
无法使用。
从key_id
(添加了强调):
然后,如果索引的初始列(列a,b等)以WHERE子句形式出现,则可以使用索引。索引的初始列必须与=或IN或IS运算符一起使用。 [使用的最右边的列可以使用不等式。对于使用的索引的最右边的列,最多可能有两个不等式必须将列的允许值夹在两个极端之间。] >
正如您所发现的,将the documentation检查中的
>
切换为position
会大大提高速度-使用三个相等性检查意味着整个索引可用于查找匹配的行。
如果您重新创建表时,其PK中的列顺序不同-至=
,或者以该顺序添加具有这三列的新索引,您应该会看到一个改进,因为这样可以使用整个索引查找要联接的行,而不仅仅是索引的一部分,因为它遵循以下约束:除了最右边的列之外,所有列都使用相等性测试。