两类隐蔽的不能利用索引的case:
(1)表列类型,与where值类型,不一致;
(2)join表的字符编码不同;
知识点1(热身):负向查询(id!=xxx)不能命中索引,会导致全表扫描。
知识点2(划重点):允许空值,不等于(!=)查询,可能导致不符合预期的结果。
a 1
b 2
c null
select * from xxx where value!=1
只会查到b 2,null无法与1比较,不会命中 。
知识点3(附加):某些or条件,又可能导致全表扫描,此时应该优化为union。
select * from xxx where value!=1 or value!=null
会导致全表扫描,而分开or,分别查询则会命中索引。
这种场景应该使用union
select * from xxx where value!=1
union
select * from xxx where value!=null
总结
(1)负向比较(例如:!=)会引发全表扫描;
(2)如果允许空值,不等于(!=)的查询,不会将空值行(row)包含进来,此时的结果集往往是不符合预期的,此时往往要加上一个or条件,把空值(is null)结果包含进来;
(3)or可能会导致全表扫描,此时可以优化为union查询;
(4)建表时加上默认(default)值,这样能避免空值的坑;
(5)explain工具是一个好东西;