执行以下代码会创建一个包含两列的表,并添加100万行。一列是INT,一列是TEXT。然后它为每列创建一个索引,每列创建一个collate nocase
索引。然后它执行三个查询。
第一个查询按预期使用索引t2
。
第二个查询与第一个查询相同,但是它添加了ESCAPE
子句并且没有使用索引。非转义%
或_
的存在应该会阻止索引被(完全)使用,但ESCAPE
子句本身的存在不应该。
为什么ESCAPE
子句阻止索引被使用?
第三个查询与第一个查询相同,但它没有使用索引。唯一的区别是查询使用列col_i
而不是col_t
,而INT
定义为TEXT
而不是.timer on
DROP TABLE IF EXISTS tab;
CREATE TABLE tab (col_t TEXT, col_i INT);
INSERT INTO tab (col_i, col_t) WITH RECURSIVE cte (x, y) AS (SELECT hex(randomblob(16)), hex(randomblob(16)) UNION ALL SELECT hex(randomblob(16)), hex(randomblob(16)) FROM cte LIMIT 1000000) SELECT x, y FROM cte;
CREATE INDEX t ON tab (col_t);
CREATE INDEX t2 ON tab (col_t COLLATE nocase);
CREATE INDEX i ON tab (col_i);
CREATE INDEX i2 ON tab (col_i COLLATE nocase);
SELECT * FROM tab WHERE col_t LIKE 'abcabcabc';
SELECT * FROM tab WHERE col_t LIKE 'abcabcabc' ESCAPE '\';
SELECT * FROM tab WHERE col_i LIKE 'abcabcabc';
。 Sqlite并没有阻止我创建索引,所以我希望它可以被使用。
为什么不使用索引i2?
LoadError on line ["55"] of ~/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb: cannot load such file -- susy
答案 0 :(得分:2)
当索引可用于LIKE时的documentation文档:
- 左侧...必须是具有TEXT亲和力的索引列的名称。
- 右侧......必须是...字符串文字...不以通配符开头。
- ESCAPE子句不能出现在LIKE运算符上。
- 用于实现LIKE的内置函数不得使用sqlite3_create_function()API重载。
- [...]
- ...必须使用内置的NOCASE整理顺序对列进行索引。
醇>
查询优化器必须证明使用索引不能改变查询的含义。这些规则实施了证明。
虽然存在可能与索引一起使用的查询,尽管违反了这些规则,但有必要扩展优化器以便能够证明它们的工作。