为什么SQLite在WHERE子句中使用文字列值时不使用索引?

时间:2016-07-04 15:18:54

标签: sqlite

这是sqlfiddle of my example,但让我解释一下:

当我有一个这样的简单表格时:

CREATE TABLE ForgeRock
    (`id` int, `productName` varchar(7), `description` varchar(55))
;

productName列上的简单索引如下:

CREATE INDEX test_idx ON ForgeRock(productName);

我可以使用WHERE子句中的productName轻松选择数据,并且正在使用我的索引。好的。

当我将硬编码值添加到我选择的列列表中时,它也运行良好并且也使用了索引:

SELECT
  0 as foo,
  0 as bar,
  productName,
  description
FROM
  ForgeRock
WHERE (foo = 0 AND productName IN ('OpenIDM', 'OpenDJ'))

即使在WHERE子句中使用硬编码的foo列仍然使用索引(应该如此)。但这是我的问题:为什么在将OR (foo = 1 AND bar IN (1))添加到WHERE子句时不使用索引?

SELECT
  0 as foo,
  0 as bar,
  productName,
  description
FROM
  ForgeRock
WHERE (foo = 0 AND productName IN ('OpenIDM', 'OpenDJ')) OR (foo = 1 AND bar IN (1)); 

任何帮助将不胜感激。再次here's the sqlfiddle

1 个答案:

答案 0 :(得分:0)

documentation说:

  

通过OR而不是AND连接的WHERE子句约束可以处理[...]
  对于任何给定的查询,可以使用此处描述的OR子句优化这一事实并不能保证它将被使用。 SQLite使用基于成本的查询计划程序来估计各种竞争查询计划的CPU和磁盘I / O成本,并选择它认为最快的计划。如果WHERE子句中有许多OR术语,或者单个OR子句子项的某些索引不是非常有选择性,那么SQLite可能会认为使用不同的查询算法甚至是全表扫描更快。