真实测NULL的相等比较、三值逻辑的短路规则,以及NOT IN列表里混入NULL会怎样真实影响整条查询,最后验证IS NULL到底能不能用上索引。
代码SELECT NULL = NULL AS a, NULL <=> NULL AS b, (1=1) AND NULL AS c, (1=0) AND NULL AS d; SELECT 5 IN (1,2,NULL) AS in_result, 5 NOT IN (1,2,NULL) AS not_in_result;
NULL = NULL → NULL (不是true!两个"未知"比较,结果还是"未知") NULL <=> NULL → 1 (NULL-safe等于运算符,真实把NULL当成一个确定的值处理) (1=1) AND NULL → NULL (true AND 未知 = 未知) (1=0) AND NULL → 0 (false AND 任何东西 = false,真实的短路)
普通的=运算符真实遵循严格的三值逻辑:任何值(包括NULL自己)和NULL比较,结果都真实是NULL(未知),不是true也不是false。只有专门的<=>(NULL-safe相等)运算符会真实把两个NULL当作相等处理。(1=0) AND NULL返回0而不是NULL,是因为AND运算符真实做了短路:只要有一边确定是false,不管另一边是什么,整体真实必然是false。
5 IN (1,2,NULL) → NULL (不是false!5确实不在1,2里,但列表里的NULL让结果变成"不确定") 5 NOT IN (1,2,NULL) → NULL (同理,也不是true) 1 IN (1,2,NULL) → 1 (1真实命中了,这种情况不受NULL影响)
SELECT * FROM null_idx WHERE val IS NULL;
-> Filter: (null_idx.val is null)
-> Covering index lookup on null_idx using idx_val (val = NULL) ← 真实走了索引查找虽然NULL没法参与普通的比较运算,但IS NULL是一个专门的谓词,InnoDB的索引真实把NULL值当作一种可以被索引和定位的"值"来存储,IS NULL查询真实能直接走索引查找,不需要全表/全索引扫描。
每一步都是本文上面用真实查询跑出来的原始结果。
<=>(NULL-safe相等) vs 普通=