我有一个像
这样的查询select * from tbl where name like 'a%' or name like 'abc%';
SQLite是否分别搜索'a%'和'abc%'?它会检查abc%是否包含在%中,并且只进行一次搜索?
“解释查询计划”返回
"0" "0" "0" "SEARCH TABLE traces USING PRIMARY KEY (name>? AND name<?)"
"0" "0" "0" "SEARCH TABLE traces USING PRIMARY KEY (name>? AND name<?)"
这是在运行时发生的事情吗?
答案 0 :(得分:1)
SQLite是否分别搜索'a%'和'abc%'?它会检查abc%是 包含在%中,只进行一次搜索?
我认为 都不是正确答案,因为它似乎介于给定的两个选项之间。
我认为在文档中拖曳会解释一下。
第一个停靠点是The SQLite Query Optimizer Overview 。这说: -
如果WHERE子句由OR分隔的约束组成 运营商然后整个条款被认为是一个单一的“术语” 应用OR子句优化。
在EXPLAIN QUERY PLAN {Add。}中指出: -
如果查询的WHERE子句包含OR表达式,那么SQLite 可能会使用“OR by union”策略(此处也会介绍)。
在此 case将有两个SEARCH记录,每个索引一个,带有 “order”和“from”列中的值相同。例如:
sqlite> CREATE INDEX i3 ON t1(b); sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2; 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?) 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
所以似乎正在使用“OR by union”策略: -
"0" "0" "0" "SEARCH TABLE traces USING PRIMARY KEY (name>? AND name<?)"
"0" "0" "0" "SEARCH TABLE traces USING PRIMARY KEY (name>? AND name<?)"
Or-clause 优化,在此解释: - 3.0 OR optimizations(与第一份文件相同)。但是有很多 mights ,而我认为EXPLAIN QUERY PLAN中提供给1.8. OR-Connected Terms In The WHERE Clause的链接更为贴切,其中包括: -
<强> 1.8。 WHERE条款中的OR-Connected条款
多列索引仅在WHERE中的约束条件时有效 查询的子句由AND连接。所以Idx3和Idx4很有帮助 当搜索既是桔子又长大的物品时 加利福尼亚州,但如果我们想要的话,这两个指数都不会有用 橙色或在加利福尼亚种植的物品。
SELECT price FROM FruitsForSale WHERE fruit='Orange' OR state='CA';
当遇到WHERE子句中的OR连接术语时,SQLite 分别检查每个OR术语并尝试使用索引来查找 与每个术语相关联的rowid。然后它需要联合 生成rowid集以查找最终结果。如下图 说明了这个过程:
上图表明SQLite计算所有rowid 首先,然后在开始之前将它们与联合操作结合起来 在原始表上执行rowid查找。实际上,rowid查找 穿插了rowid计算。 SQLite在a处使用一个索引 时间找到rowid,同时记住之前看过的rowid 以免重复。这只是一个实现细节, 虽然。该图虽然不是100%准确,但却提供了很好的概述 发生了什么。
为了使上面显示的OR-by-UNION技术有用,那里 必须是可用的索引,以帮助解决每个OR连接的术语 在WHERE子句中。如果连一个OR连接的术语都没有 索引,然后必须进行全表扫描才能找到 由一个术语生成的rowid,以及SQLite是否必须完整 表扫描,它也可以在原始表上完成并得到所有 一次通过的结果,而不必混淆工会 操作和后续二进制搜索。
人们可以看到如何利用OR-by-UNION技术 在WHERE子句具有术语的查询上使用多个索引 通过AND连接,使用交叉运算符代替联合。 许多SQL数据库引擎都会这样做。但性能提升 过度使用单个索引是轻微的,所以SQLite没有 此时实施该技术。但是,未来的版本 可以增强SQLite以支持AND-by-INTERSECT。
另一个考虑因素是4.0 The LIKE optimization。但是,我认为这只是基于LIKE子句。