






















在mysql 配置文件中 (my.conf),进行下面配置,修改配置后重启mysql生效。
# 开启或关闭慢查询日志 slow_query_log = ON # 慢查询记录时间阈值,SQL执行超过此时间则会被记录到日志(单位:秒,默认10秒)。 long_query_time = 5 # 指定生成的慢查询日志路径(未设置则和默认和数据文件放一起) slow_query_log_file = /opt/soft/mysql/log/slow.log # 是否记录未使用索引的SQL。 log_queries_not_using_indexes=on
设置全局变量(MySQL重启后失效,不建议)
set global slow_query_log = on; set global log_output = 'FILE,TABLE'; set global long_query_time = 0.001;
慢SQL优化办法:
创建联合索引时列的选择原则
经常用的列优先(最左匹配原则)
离散度高的列优先(离散度高原则)
宽度小的列优先(最少空间原则)
select 学号,成绩 from 成绩表 where 学号 in(8,9);
优化后:
select 学号,成绩 from 成绩表 where 学号 between 8 and 9;
select 学号 from 成绩表 where 成绩=88 or 成绩=89;
优化后:
select 学号 from 成绩表 where 成绩=88 union select 学号 from 成绩表 where 成绩=89
like查询以%开头时索引失效:
select * from doc where title like ‘%XX’; --不能使用索引 select * from doc where title like ‘XX%’; --非前导模糊查询,可以使用索引
反向条件不走索引:负向条件有:!=、<>、not in、not exists、not like 等
select * from doc where status != 1 and status != 2; --不能使用索引 select * from doc where status in (0,3,4); --优化为 in 查询,可以使用索引
IS NULL、IS NOT NULL 在无法使用索引,不过在mysql的高版本已经做了优化,允许使用索引
在索引列做任何操作(计算、函数、表达式)会导致索引失效而转向全表扫描
select * from doc where YEAR(create_time) <= ‘2016’; – 不能使用索引 select * from doc where create_time<= ‘2016-01-01’; – 可以使用索引 select * from order where date < = CURDATE(); – 不能使用索引 select * from order where date < = ‘2018-01-2412:00:00’; – 可以使用索引 select id from t where substring(name,1,3)=’abc’ – 不能使用索引 select id from t where name like ‘abc%’ – 可以使用索引 select id from t where num/2=100 – 不能使用索引 select id from t where num=100*2 – 可以使用索引
强制类型转换会导致全表扫描 :字符串类型不加单引号会导致索引失效,因为mysql会自己做类型转换,相当于在索引列上进行了操作。
select * from user where phone=13800001234; – 不能使用索引 select * from user where phone=‘13800001234’; – 可以使用索引
使用组合索引时,要符合最左前缀原则: :组合索引的字段数不允许超过5个。如果在a,b,c三个字段上建立联合索引 index(a,b,c),那么他会自动建立 a、(a,b)、(a,b,c) 三组索引。
索引失效情况总结:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
Like百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用。
一些常见的索引优化技巧包括:
consts:单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。 ref:使用普通的索引 range:对索引进行范围检索。 当 type=index 时,索引物理文件全扫,速度非常慢。
进行join联表查询的字段需要建立索引,join最好不要超过三个表,需要 join 的字段,数据类型必须一致: 多表关联查询时,保证被关联的字段需要有索引。left join是由左边决定的,左边的数据一定都有,所以右边是我们的关键点,建立索引要建右边的。当然如果索引在左边,可以用right join。
减少请求的数据量:
优化深度分页的场景:利用延迟关联或者子查询:对于 limit m, n 的分页查询,越往后面翻页(即m越大的情况下)SQL的耗时会越来越长,对于这种应该先取出主键id,然后通过主键id跟原表进行Join关联查询。因为MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。延迟关联示例如下,先快速定位需要获取的 id 段,然后再关联:
延迟关联:通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据 覆盖索引:select的数据列只用从索引中就能够得到,不用回表查询 select a.* from 表1 a,(select id from 表1 where 条件 limit 100000,20) b where a.id=b.id;
深度分页原理:limit m,n查询过程是先回表查询m+n条记录,然后丢掉前m条,取后面n条结果返回。内存占用和IO读取开销太大
避免在使用or来连接查询条件:如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描。
小表驱动大表,即小的数据集驱动大的数据集:
Using filesort
Using filesort 的含义很简单,就是使用了排序操作,出现这个选项的常见情况就是 Where 条件和 order by 子句作用在了不同的列上
解决办法:建立联合索引,对where条件列和order by列建立联合索引。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。