1. 使用or操作符
当where语句中使用or操作符并且or两边的条件涉及到至少两个字段时,MySQL无法使用索引,会转向全表扫描。因此,应尽量避免使用or操作符。
原因:因为MySQL中的索引是根据某个字段进行排序建立的。当使用or操作符,说明有两个条件其中某个条件成立即可,而我们使用某个索引时只能判断出对应字段的条件是否成立,即使不成立,另一个条件成立时该记录也符合我们要查询的结果。所以使用索引无法做出判断。
-- id为主键索引
EXPLAIN SELECT * FROM t_b2b_contract WHERE id > 1 OR remark = 'zs';
type类型all,是全表扫描
EXPLAIN SELECT * FROM t_b2b_contract WHERE id <1 OR id >6;
type类型range,范围查询用到索引
-- 唯一索引
EXPLAIN SELECT * FROM t_b2b_contract WHERE contract_no = "7c5718ecbc5a8284ae56918a6bb26434" OR mno = '20221008210722022119128683';
type类型all,全表扫描
-- 组合索引
EXPLAIN SELECT * FROM t_b2b_contract WHERE contract_no = "7c5718ecbc5a8284ae56918a6bb26434" OR user_id = '20221008210722022119128683';
2. 复合索引失效
如果使用了复合索引,但查询时未使用索引的第一列,索引也会失效。(最左原则)
比如组合索引:KEY idx_collect_order_no_contract_no (collect_order_no,contract_no) COMMENT '收款单号、合同编号联合索引'\
-- collect_order_no、contract_no列建立了符合索引;
explain select * from t_b2b_collect_order_contract_relation where contract_no ="1929110298828"
type类型为all 全表扫描(contract_no)
type为ref 索引生效(collect_order_no and contract_no)
type为ref 索引生效(collect_order_no)
3. like查询
如果使用了like且以%开头,则索引会失效。(右模糊失效)
如果使用了like且以%结束,则索引生效。(左模糊生效)
4. 索引列上使用函数
原因:因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。
mysql 隐式类型转换
上述案例其真实的原因时mysql的隐式类型转换,那什么是隐式类型转换呢?
5. 隐式类型转换 --隐式类型转换规则 官方文档
如果一个或两个参数均为NULL,则比较的结果为NULL,除了 相等比较运算符。对于NULL NULL,结果为true。
如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。
如果两个参数都是整数,则将它们作为整数进行比较。
如果不与数字比较,则将十六进制值视为二进制字符串。
如果参数之一是 timestamp 或 datatime column,而另一个参数是常量,则在执行比较之前,该常量将转换为时间戳。
如果参数之一是十进制值,则比较取决于另一个参数。
如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较;如果另一个参数是浮点值,则将参数作为浮点值进行比较。
在所有其他情况下,将参数作为浮点数(实数)进行比较。
例如,将字符串和数字操作数进行比较,将其作为浮点数的比较。
通过隐式类型转换可以得出上述示例的结果:
当查询中有数字时那么会将字符串转化成数字进行比较。
所以当你的列为字符串时那么需要将列中字符串进行类型格式转换而进行字符格式转换之后则与索引不一致;
当你的列为数字时查询等式为字符串时只是把查询的常量转成数字并不影响列的类型所以依然可以使用索引并没有破坏索引的类型。
- 隐式类型转换实例
type为all 索引失效
type为ref 索引生效
5. 对索引进行表达式计算
原因:因为索引保存的是索引字段的原始值,而不是 contract_no + 1 表达式计算后的值,所以无法走索引,
只能通过把索引字段的取值取出来,然后进行表达式的计算来进行条件判断,因此采用的就是全表扫描的方式。\
type为all 索引失效