MySQL性能优化之优化JOIN和优化原则

时间:2024-03-16 14:21:49

一.优化JOIN

(1).理解JOIN原理
MySQL是只支持一种JOIN算法Nested-Loop Join(嵌套循环链接),不过MySQL的Nested-Loop Join(嵌套循环链接)也是有很多变种,能够帮助MySQL更高效的执行JOIN操作:
举个例子:
select * from t1 inner join t2 on t1.id=t2.tid
(1)t1称为外层表,也可称为驱动表。
(2)t2称为内层表,也可称为被驱动表。

①.Simple Nested-Loop Join
简单嵌套循环连接
ALL,全表扫描

②.Index Nested-Loop Join
索引嵌套循环连接
被驱动表的查询等值条件,应该是被驱动表中的索引

③.Block Nested-Loop Join
缓存块嵌套循环连接
将驱动表中的数据缓存到buffer中,再打包去查询被驱动表,减少访问次数

(2).join优化原则
1.小结果集驱动大结果集
用小结果集驱动大结果集,减少外层循环的数据量:
如果小结果集和大结果集连接的列都是索引列,mysql在内连接时也会选择用小结果集驱动大结果集,因为索引查询的成本是比较固定的,这时候外层的循环越少,join的速度便越快。

2,为匹配的条件增加索引
争取使用INLJ,减少内层表的循环次数

3.增大join buffer size的大小
当使用BNLJ时,一次缓存的数据越多,那么外层表循环的次数就越少
缓冲区默认大小: 256K
查看缓冲区大小:
show variables like ‘join_%’;
可以再mysql的配置文件my.ini中配置缓存区大小:
在[mysqld] 这个节点下配置:
join_buffer_size = 8M

4.减少不必要的字段查询
(1)当用到BNLJ时,字段越少,join buffer 所缓存的数据就越多,外层表的循环次数就越少;
(2)当用到INLJ时,如果可以不回表查询,即利用到覆盖索引,则可能可以提高速度

二.其他优化

(1).优化ORDER BY
1.ORDER BY 实现原理:
①,通过有序索引而直接取得有序的数据;
②,通过MySQL 的排序算法将存储引擎中返回的数据进行排序然后再将排序后的数据返回;

2.排序算法
①双路排序
1)读取 固定长度的排序列 + rowid组成元组,放入sort buffer
2) 如果sort buffer满, 根据排序列执行一次quicksort, 将其写入临时文件
3)重复1 2 步骤直到文件结束,
4)对临时文件执行归并排序
5)根据排序好的rowid 读取查询需要的行
MySQL性能优化之优化JOIN和优化原则
②.单路排序:
1)读取<固定长度的排序列, 需要返回的列> 组成元组,放入sort buffer
2) 如果sort buffer满, 根据排序列执行一次quicksort, 将其写入临时文件
3)重复1 2 步骤直到文件结束,
4)对临时文件执行归并排序
5)从排好序的临时文件中读取需要返回的列即可
MySQL性能优化之优化JOIN和优化原则
两种的区别
1)双路排序会读取两次表, 且第二次是随机读取的
2)单路排序的元组比双路排序要长,导致它需要多次向临时文件写入内容,增加IO操作,当需要返回的列的总长度很长时尤其明显。
MySQL根据max_length_for_sort_data变量来确定使用哪种算法,默认值是1024字节,如果需要返回的列的总长度大于max_length_for_sort_data,使用第一种算法,否则使用第二种算法。
查看:show variables like ‘max_sort_length’;

using temporary优化:
ySQL 执行查询语句, 对于order by谓词,可能会使用filesort或者temporary。比如explain一条语句的时候,会看到Extra字段中可能会出现,using filesort和using temporary。
具体请参考下面的文章
http://mysql.taobao.org/monthly/2015/03/04/

3.优化方案:
1,加大max_length_for_sort_data 参数;
2,去掉不必要的返回字段;
3,增大sort_buffer_size 参数;

(2).优化GROUP BY
GROUP BY的前提是排序,所以优化手段和ORDER BY是一样的。

(3).优化DISTINCT
实质上还是在优化ORDER BY

三.SQL优化原则

(1).选择需要优化的SQL
1,优先优化高并发低消耗的SQL;
1,1小时请求1W次,1次10个IO;
2,1小时请求10次,1次1W个IO;
从IO消耗,优化难度,CPU消耗进行比较;
2,定位性能瓶颈;
1,SQL运行较慢有两个影响原因,IO和CPU,明确性能瓶颈所在;
2,明确优化目标;

(2).Explain和Profile
1,任何SQL的优化,都从Explain语句开始;Explain语句能够得到数据库执行该SQL选择的执行计划;
2,首先明确需要的执行计划,再使用Explain检查;
3,使用profile明确SQL的问题和优化的结果;

(3).永远用小结果集驱动大的结果集
JOIN原则;
1,不是小表驱动大表,是小结果集驱动大结果集;

(4).在索引中完成排序

(5).使用最小Columns
1,特别是需要使用column排序的时候;
2,减少网络传输数据量;
3,MYSQL排序原理,是把所有的column数据全部取出,在排序缓存区排序,再返回结果;如果column数据量大,排序区容量不够的时候,就会使用先column排序,再取数据,再返回的多次请求方式;

(6).使用最有效的过滤条件
1,过多的WHERE条件不一定能够提高访问性能;
2,一定要让where条件使用自己预期的执行计划;

(7).避免复杂的JOIN和子查询
1,复杂的JOIN和子查询,需要锁定过多的资源,MYSQL在大量并发情况下处理锁定性能下降较快;
2,不要过多依赖SQL的功能,把复杂的SQL拆分为简单的SQL;
3,MySQL子查询性能较低,应尽量避免使用;

优化的案例:
仅供参考
https://tech.meituan.com/2014/06/30/mysql-index.html