此查询不会使用索引: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
,但我仍然很好奇为什么会这样。
答案 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,因此无用。
因此,IS
和IS NOT
仅在与NULL
操作数一起使用时才有用。使用常规文字操作数,它与=
(或!=
)相同。并且IS NULL
可以通过索引来满足。