欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
MySQL 无论是在面试还是工作使用中,最重要的就是对 SQL 语句进行性能优化
优化的关键就是 索引 ,MySQL 通过提供索引功能来加快对数据的查询速度,而有时因为我们不当的操作导致 SQL 查询语句并没有走索引,导致速度没有达到期望的结果
所以要想对 SQL 进行优化,就一定要了解 MySQL 在哪些情况下不会走索引,以及如果要建立索引,该怎么去建立
MySQL 索引失效的原因一般就分为两种:
接下来说一下 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 前后的任何一个条件列不是索引列,那么索引就会失效
select * from emp where id = 10010 or name = 'abcd';
如上,假如 name 列不是索引列,即使 id 列上有索引,这个查询语句也不会走索引
select * from emp where name is null;
如上,name 字段存在 null 值,索引会失效
应该尽量避免索引列的值为 null,可以在创建表的时候设置默认值或者将 null 替换为其他特殊值。
了解了 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))
有些 SQL 查询语句是需要通过 order by 进行排序的,那么可能 where 的条件和 order by 的条件不同,那么这时要优先根据 where 条件的字段设计索引
因为先通过 where 条件使用索引筛选出来一小部分指定的数据,再通过 order by 去进行排序,性能消耗要小很多
慢 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 相关的配置信息
默认情况下慢查询日志是关闭的,开启慢查询日志会带来一定的性能影响,因此建议只在调优期间开启