Sqlite没有使用某些索引

时间:2016-10-24 21:18:15

标签: sqlite

执行以下代码会创建一个包含两列的表,并添加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

1 个答案:

答案 0 :(得分:2)

当索引可用于LIKE时的documentation文档:

  
      
  1. 左侧...必须是具有TEXT亲和力的索引列的名称。
  2.   
  3. 右侧......必须是...字符串文字...不以通配符开头。
  4.   
  5. ESCAPE子句不能出现在LIKE运算符上。
  6.   
  7. 用于实现LIKE的内置函数不得使用sqlite3_create_function()API重载。
  8.   
  9. [...]
  10.   
  11. ...必须使用内置的NOCASE整理顺序对列进行索引。
  12.   

查询优化器必须证明使用索引不能改变查询的含义。这些规则实施了证明。

虽然存在可能与索引一起使用的查询,尽管违反了这些规则,但有必要扩展优化器以便能够证明它们的工作。