为什么SQLite在使用“IS”而不是“=”时不使用索引?

时间:2013-11-21 07:17:36

标签: sql sqlite indexing

此查询不会使用索引:SELECT * FROM baz WHERE id IS '123'

http://sqlfiddle.com/#!7/7e299/2

此查询将使用索引:SELECT * FROM baz WHERE id='123'

http://sqlfiddle.com/#!7/7e299/1

为什么?

编辑:我意识到有一个愚蠢的答案是扩展IS以获得正确的效果(即进行查询SELECT * FROM baz WHERE id='123' OR '123' IS NULL,但我仍然很好奇为什么会这样。

1 个答案:

答案 0 :(得分:3)

无需支持此类查询的索引。

首先,这就是query optimizer works

的方式
To be usable by an index a term must be of one of the following forms:

  column = expression
  column > expression
  column >= expression
  column < expression
  column <= expression
  expression = column
  expression > column
  expression >= column
  expression < column
  expression <= column
  column IN (expression-list)
  column IN (subquery)
  column IS NULL

对于IS运算符,NULL values are special

  

IS和IS NOT运算符的工作方式类似于=和!=,除非一个或两个操作数都为NULL。在这种情况下,如果两个操作数均为NULL,则IS运算符求值为1(true),IS NOT运算符求值为0(false)。如果一个操作数为NULL而另一个操作数不为NULL,则IS运算符的计算结果为0(false),IS NOT运算符为1(true)。

在你的问题中,

SELECT * FROM baz WHERE id IS '123'

SELECT * FROM baz WHERE id='123' OR id IS NULL

不是一回事。 (后者可以使用两个索引查找来满足。)它应该类似于

SELECT * FROM baz WHERE id='123' OR (id IS NULL AND '123' IS NULL)

其中带括号的表达式始终为false,因此无用。

因此,ISIS NOT仅在与NULL操作数一起使用时才有用。使用常规文字操作数,它与=(或!=)相同。并且IS NULL可以通过索引来满足。