【面试进阶之路】MySQL 查询优化最佳实践

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

MySQL 查询优化最佳实践

【面试进阶之路】MySQL 查询优化最佳实践_第1张图片

MySQL 无论是在面试还是工作使用中,最重要的就是对 SQL 语句进行性能优化

优化的关键就是 索引 ,MySQL 通过提供索引功能来加快对数据的查询速度,而有时因为我们不当的操作导致 SQL 查询语句并没有走索引,导致速度没有达到期望的结果

所以要想对 SQL 进行优化,就一定要了解 MySQL 在哪些情况下不会走索引,以及如果要建立索引,该怎么去建立

MySQL 索引失效

MySQL 索引失效的原因一般就分为两种:

  • 第一种情况是 MySQL 认为不走索引,直接进行全表扫描,速度更快,所以不走索引
  • 第二种情况是 MySQL 想走索引,但是 SQL 语句中给的条件无法走索引,导致不走索引

接下来说一下 MySQL 索引失效的几种情况,在实际使用的时候,要尽量避免索引失效的情况:

  • 使用左模糊查询
select id,name,age,salary from table_name where name like '%lucs';

在进行 SQL 查询时,要尽量避免左模糊查询,可以改为右模糊查询,在右模糊查询的情况下一般都会走索引

select id,name,age,salary from table_name where name like 'lucs%';
  • 不符合最左前缀原则的查询

对于联合索引(a,b,c),来说,不能直接用 b 和 c 作为查询条件而直接跳过 a,这样就不会走索引了

如果查询条件使用 a,c,跳过了 b,那么只会用到 a 的索引

  • 联合索引的第一个字段使用范围查询

比如联合索引为:(name,age,position)

select * from employees where name > 'LiLei' and age = 22 and position ='manager';

如上,联合索引的第一个字段 name 使用范围查询,那么 InnoDB 存储引擎可能认为结果集会比较大,如果走索引的话,再回表查速度太慢,所以干脆不走索引了,直接全表扫描比较快一些

可以将范围查询放在联合索引的最后一个字段

  • 对索引列进行了计算或函数操作

当你在索引列上进行计算或者使用函数,MySQL 无法有效地使用索引进行查询,索引在这种情况下也会失效,如下:

select * from employees where LEFT(name,3) = 'abc';

应该尽量避免在查询条件中对索引字段使用函数或者计算。

  • 使用了 or 条件

当使用 or 条件时,只要 or 前后的任何一个条件列不是索引列,那么索引就会失效

select * from emp where id = 10010 or name = 'abcd';

如上,假如 name 列不是索引列,即使 id 列上有索引,这个查询语句也不会走索引

  • 索引列上有 Null 值
select * from emp where name is null;

如上,name 字段存在 null 值,索引会失效

应该尽量避免索引列的值为 null,可以在创建表的时候设置默认值或者将 null 替换为其他特殊值。

MySQL 的索引设计原则

了解了 MySQL 索引失效的情况之后,我们要对表设计索引,来尽量让查询语句都可以使用到索引

一般索引设计要遵循以下几条原则:

  • 代码先行,索引后上

索引不要在建完表之后立马建立索引,而是要等主体业务功能开发完毕之后,把该表相关的 SQL 语句进行分析之后,再建立索引

  • 覆盖索引

联合索引要尽量设计成覆盖索引,也就是让联合索引包含所有查询的字段,这样就避免了 MySQL 在二级索引中拿不到所有的数据还要回表查询的情况出现

  • 索引的选择性

索引的选择性是指不重复的记录与总记录的比值,选择性越高,表明通过索引可以过滤出更多的数据,查询效率也就越高

这里举一个反例,对性别字段建立索引,由于性别字段只有 3 种(男、女、未知),选择性很小,通过性别根本筛选不掉太多的数据,有没有索引区别不大

  • 长字符串采用前缀索引

采用前缀索引即只对长字符串的前一部分字符进行索引

这样做虽然提高了索引的性能,并且节省索引的空间,但是存在的缺点就是:降低了索引的选择性

那么对长字符串的前多少位建立索引也是就讲究的,可以通过下边这个 SQL 语句来计算不同长度的前缀索引的选择性,随着前缀长度的增长,选择性逐渐稳定时,就选择对应的前缀索引长度

# 长度为 6 的前缀索引的选择性
select count(distinct left(title, 6)) / count(*) as sel6 from table_name

如何建立前缀索引?alter table table_name add key(title(6))

  • where、order by 索引设计冲突时,优先 where 设计

有些 SQL 查询语句是需要通过 order by 进行排序的,那么可能 where 的条件和 order by 的条件不同,那么这时要优先根据 where 条件的字段设计索引

因为先通过 where 条件使用索引筛选出来一小部分指定的数据,再通过 order by 去进行排序,性能消耗要小很多

  • 基于慢 SQL 做优化

慢 SQL 是指执行时间超过一定阈值的 SQL 查询语句

慢 SQL 相关的 MySQL 参数:

  • slow_query_log:是否开启慢查询日志,默认关闭,通过 SHOW VARIABLES LIKE '%slow_query%'
  • long_query_time:设置慢查询的时间阈值,默认 10s,通过 SHOW VARIABLES LIKE '%long_query_time%'; 查询
  • log-slow-queries:慢查询的日志存储路径(MySQL 5.6 版本及以下)
  • slow-query-log-file:慢查询的日志存储路径(MySQL 5.6 版本及以上)

通过命令 SHOW VARIABLES LIKE '%slow_query%' 可以查询慢 SQL 相关的配置信息

默认情况下慢查询日志是关闭的,开启慢查询日志会带来一定的性能影响,因此建议只在调优期间开启

你可能感兴趣的:(面试进阶之路,面试,mysql)