mysql 调优-索引失效

范围条件放最后面,不管单列还是多列索引,把能过滤最多的索引放前面

  • 用不用索引最终都是优化器决定的,EXPLAIN json 格式里的执行成本决定

  • 最左匹配,如果是联合索引,查找索引树的时候,只能根据第一个索引才能找到第二个第三个,如果顺序没对就不会走索引

-- 联合索引(name, code, addr)
-- 这个虽然顺序没对,但是三个字段都用上了,优化器会给我们换 where 顺序,所以会走索引
select * from t_user where name ... and addr...and code...

-- 这个会走一半,可以根据 EXPLAIN 看其 key_length
-- 因为 name 是联合索引第一个,所以 name 会走索引,但是第二个索引是 code,这里跳过了 code,所以后面的 addr 不会走索引
select * from t_user where name... and addr...

-- 不会走索引,跳过了第一个
select * from t_user where code... and addr...

-- 会走索引
select * from t_user where name... 
  • 计算,函数,类型转换(自动会手动)导致索引失效
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = 'abc';
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age+1 = 20;
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE name=123;
  • 范围条件右边的列索引会失效(不是where条件的右边,是联合索引的右边)
-- 联合索引 age,name
-- age 会走索引
select * from t_user where age > 18 and name = 'xxx';

-- 联合索引与where位置无关(优化器会优化),结果还是 age 会走索引,name 不会
-- 优化器优化后的sql是 ... where age > 18 and name = 'xxx'
-- 如果真要这样干,那就再建立个联合索引 name, age
select * from t_user where name = 'xxx' and age > 18;
  • 不等值查询不会走索引,where name <> xxx

  • is not null 不会走索引(is null 会走,所以建议列约束设置为不为空)

  • like % 开头不走索引

  • or 前后存在非索引列不走索引,除非所有的 or 列都有索引

posted @ 2023-05-17 16:05  CyrusHuang  阅读(21)  评论(0编辑  收藏  举报