MySQL 更好的语句
本文将介绍如何写出更好的 SQL 语句。
一、避免索引失效
1. 避免联合索引失效
假设创建了联合索引
name, age, address
(1) 全值匹配
如果索引中每个列都有对应的 “等值” 查询条件,无论顺序如何,索引都会生效且执行效率最高
1 |
|
(2) 最左前缀法则
如果查询条件未具体对应到索引中每个列,则应该遵循最左前缀原则,即查询条件应该从索引的最左列开始,并且不能跳过索引中的列。
1 |
|
2. 避免在索引列上进行运算操作
如果在索引列上进行运算操作,则索引将会失效。
1 |
|
3.避免强制类型转换
在实际开发中,我们可能会使用 uuid 作为表的主键,如果使用纯数字的 uuid 并且将数据库中主键类型设为 varchar,此时便会出现数据类型为字符串的纯数字。
此时,在查询时应该注意为 uuid 值手动添加单引号包裹,以避免 MySQL 的自动类型转换将其转换为数字,从而导致缓存失效。
1 |
|
4. 避免查询索引以外的字段
尽量避免使用 select *
,尽量避免查询除索引以外的其它字段,因为需要回表查询其它字段。
- 回表查询:先定位主键值,再根据主键值查询具体的行数据的现象
- 覆盖索引:查询列被索引列包含的查询
5. 避免使用 or
大多数情况下,使用 or 会导致索引失效。
6. “前模糊查询” 会导致索引失效
如果进行 “前模糊查询” 或 “前后模糊查询” 将会导致缓存失效。
1 |
|
7. 避免使用 not in
索引列 not in (···)
将会导致索引失效;
相反,索引列 in (···)
索引仍会生效。
8. 尽量使用复合索引
联合索引 name, age, address
相当于三个索引:
name
name, age
name, age, address
并且,使用单列索引时,即使三个索引都能够使用,MySQL 也不会全部使用,而是从中选择一个最优索引使用。
二、ORDER BY 优化
1. 避免 FileSort
具体请看:
尽量使用索引排序,在这种情况下,MySQL 可以将根据索引查到的记录直接返回,避免额外的 FileSort 排序,
2. FileSort 的优化
在某些情况下,FileSort 无法避免,此时也应该对 FileSort 进行优化。
- FileSort 有两种算法:
- 两次扫描算法:
- 需要两次数据读取
- 首先获取排序字段和行指针信息,排序;排序完成后,根据行指针回表读取完整记录
- 一次扫描算法:
- 内存开销大
- 一次性取出所有字段,排序,排序后直接返回结果
- 两次扫描算法:
- FileSort 进行排序时,在排序区 sort buffer 中排序,当 sort buffer 不够时,会利用临时表 temporary table 进行外排序
可以适当提升 sort_buffer_size
, max_length_for_sort_data
,使得 MySQL 尽量选择一次扫描算法,并且避免进行外排序。
三、GROUP BY 优化
一般情况下,GROUP BY 也会进行排序操作,只是额外增加了分组操作及聚合函数的计算,因此,它可以和 ORDER BY 一样进行优化。
如果希望避免排序带来的性能消耗,可以执行 ORDER BY NULL 禁止排序。
四、嵌套查询优化
可以将嵌套查询尽量优化为连接查询。
连接查询效率更高,因为 MySQL 不需要在内存中创建临时表
五、OR 优化
建议使用 union 替换 or。
六、使用建议语句优化
在 MySQL 中,可以使用 USE INDEX
,IGNORE INDEX
,FORCE INDEX
影响语句的执行计划。
参考
- MySQL 技术内幕
- MySQL 是怎样运行的:从根儿上理解 MySQL