Mysql调优策略
1.思考流程
当遇到调优问题时该如何思考?
整个流程划分成了 观察(Show status)
和 行动(Action)
两个部分。字母 S 的部分代表观察(会使 用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。
我们可以通过观察了解数据库整体的运行状态,通过性能分析工具可以让我们了解执行慢的SQL都有哪些,查看具体的SQL执行计划,甚至是SQL执行中的每一步的成本代价,这样才能定位问题所在,找到了问题,再采取相应的行动。
2.性能分析
2.1.慢查询日志
慢查询日志(Slow Query Log)是数据库管理系统的一项重要功能,它用于记录执行时间超过一定阈值的查询语句
2.1.1.开启slow_query_log
查看是否开启
1 | mysql > show variables like '%slow_query_log'; |
如果没开启,则开启日志
1 | mysql > set global slow_query_log='ON'; |
2.1.2. 修改 long_query_time 阈值
查看阈值 默认为10s
1 | mysql > show variables like '%long_query_time%'; |
可以设置阈值
1 | #global |
2.1.3.查看慢查询数目
1 | SHOW GLOBAL STATUS LIKE '%Slow_queries%'; |
2.1.4.日志分析工具
mysqldumpslow
常见使用方式
1 | #得到返回记录集最多的10个SQL |
2.1.5.关闭日志
1 | SET GLOBAL slow_query_log=off; |
2.2.分析查询语句:EXPLAIN
基本语法
1 | EXPLAIN SELECT select_options |
EXPLAIN 语句输出的各个列的作用如下:
3.索引优化
3.1.索引失效案例
计算、函数、类型转换(自动或手动)导致索引失效
情况一:函数
1 | mysql> EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = 'abc'; |
情况二:参与计算
1 | EXPLAIN SELECT SQL_NO_CACHE id, stuno, NAME FROM student WHERE stuno+1 = 900001; |
情况三:类型转换
1 | EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE name=123; #name为varchar,发生了类型转换 |
范围条件右边索引列失效
1 | INDEX idx_age_classid_name; |
应将范围查询条件放在最后
1 | #将索引改为 |
不等于索引失效
1 | CREATE INDEX idx_name ON student(NAME); |
失效
1 | EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE student.name <> 'abc'; |
is not null索引失效
- is null可以触发索引
- is not null无法触发索引
左模糊和全模糊索引失效
1 | EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE name LIKE '%ab'; |
or前后存在非索引列
在WHERE子句中,如果在OR前的条件列进行了索引,而在OR后的条件列没有进行索引,那么索引会失效。也就是说,OR前后的两个条件中的列都是索引时,查询中才使用索引。
3.2.最左前缀原则
MySQL可以为多个字段创建索引,一个索引可以包含16个字段。对于多列索引,过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。如果查询条件中没有用这些字段中第一个字段时,多列(或联合)索引不会被使用。
3.3.关联查询优化
对于内连接来说,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的
对于内连接来讲,如果表的连接条件只有一个字段有索引,则有索引的字段所在的表会被作为被驱动表
对于内连接来讲,在两个表的连接条件都存在索引的情况下,会选择小表作为驱动表。“小表驱动大表”
3.4.子查询优化
可以使用连接(JOIN)查询来替代子查询。**连接查询 不需要建立临时表
,其 速度比子查询
要快 ,如果查询中使用索引的话,性能就会更好。
3.5.排序优化
在MySQL中,支持两种排序方式,分别是 FileSort
和 Index
排序。
- Index 排序中,索引可以保证数据的有序性,不需要再进行排序,
效率更高
。 - FileSort 排序则一般在
内存中
进行排序,占用CPU较多
。如果待排结果较大,会产生临时文件 I/O 到磁盘进行排序的情况,效率较低。
优化策略
- SQL 中,可以在 WHERE 子句和 ORDER BY 子句中使用索引,目的是在 WHERE 子句中
避免全表扫描
,在 ORDER BY 子句避免使用 FileSort 排序
。当然,某些情况下全表扫描,或者 FileSort 排序不一定比索引慢。但总的来说,我们还是要避免,以提高查询效率。 - 尽量使用 Index 完成 ORDER BY 排序。如果 WHERE 和 ORDER BY 后面是相同的列就使用单索引列; 如果不同就使用联合索引。
3.6.使用覆盖索引
什么时覆盖索引
一个索引包含了满足查询结果的数据就叫做覆盖索引
4.索引设计原则
- 频繁作为 WHERE 查询条件的字段
- 字段的数值有唯一性的限制
- 经常 GROUP BY 和 ORDER BY 的列
- UPDATE、DELETE 的 WHERE 条件列
- DISTINCT 字段需要创建索引
- 多表连接时对连接条件创建索引
- 使用字符串前缀创建索引
- 区分度高(散列性高)的列适合作为索引
- 使用最频繁的列放到联合索引的左侧
其他调优策略
。。。