一 简介:今天我们来探讨下SQL语句的优化基础
二 基础规则:
一 通用:
1 避免索引字段使用函数
2 避免发生隐式转换
3 order by字段需要走索引,否则会发生filesort
4 当需要得到的数据量占用表的数据量很大比例的时候,数据库可能不会采用索引而选择全表扫描
5 复合索引要注意最左原则
6 尽量用union all 代替union
7 利用 mysql 5.7的虚拟列特性
8 利用临时表防范汇总临时结果
二 多表:
1 对于子查询要具体情况具体分析(子查询和join查询可能会相互改写转化)
2 explain所看到的第一张表为驱动表,尽量减少扫描驱动表的行数
3 多表联查一定要避免笛卡尔积
4 要注意分页查询的优化
5 join表时一定要将所有连接字段赋予索引(非常重要)
6 多表查询善用 STRAIGHT_JOIN
三 函数处理
1 采用not null is null 代替 ifnull函数,ifnull函数会降低查询性能
四 基础原理:
1 驱动表的优化原理
优化的目标是尽可能减少JOIN中Nested Loop的循环次数,以此保证:永远用小结果集驱动大结果集(Important!)!:A JOIN B,A为驱动,A中每一行和B进行循环JOIN,看是否满足条件,所以当A为小结果集时,越快。
NestedLoopJoin实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复
五 什么情况下不会用到索引
1 不符合联合索引最左原则
2 where条件中有or not in not exits等
3 like查询是以%开头
4 查询条件存在隐式转换
5 查询条件存在函数运算
6 优化器认为全表扫描的成本低于索引扫描
但是切记 由于mysql5.6的ICP特性,以上情况下可能会出现ICP特性(索引的二次过滤)
六 总结
1 一半以上的慢语句都可以通过加索引解决问题(单列索引+联合索引)
2 如果可以直接停掉的慢语句直接停掉就可以
3 对剩下慢语句 可以采用拆分+改写的方式进行
4 SSD的更换能减少随机IO的发生,提升查询效率
七 特性
icp 特性
查询流程 server层->innodb engine->数据文件
ICP特性
1 ICP可以减少存储引擎必须访问基表的次数以及MySQL服务器必须访问存储引擎的次数
2 ICP用于 range, ref, eq_ref,和 ref_or_null访问方法时,有必要访问完整的表行。
3 ICP仅用于二级索引。ICP的目标是减少全行读取的数量,从而减少I / O操作,可以理解成在server层二次过滤
八 联合索引的key_len计算方式
1 所有的索引字段,如果没有设置not null,则需要加一个字节。
2.定长字段,int占四个字节,bigint占八个字、char(n)占n个字符。
3 DATE 3 个字节 DATETIME 8 个字节 TIMESTAMP 4 个字节
4.对于变成字段varchar(n),则有n个字符+两个字节。
5.不同的字符集,一个字符占用的字节数不同。latin1编码的,一个字符占用一个字节,gbk编码的,一个字符占用两个字节,utf8编码的,一个字符占用三个字节 utf8mb4编码的,一个字符占用4个字节
6 key_len只指示了where中用于条件过滤时被选中的索引列,是不包含order by/group by这一部分被选中的索引列的,所以可能存在排序用到索引但是key_len不对等的情况,这里要注意
INNODB的索引会限制单独Key的最大长度为767字节,联合索引的单列项同样如此
九 STRAIGHT_JOIN 一些注意点
1 STRAIGHT_JOIN 只适用于inner join,因为其他join都指定了顺序
2 STRAIGHT_JOIN 在多表join情况下都必须进行替换
3 STRAIGHT_JOIN 目的就是调整驱动表选择的顺序
4 table1 STRAIGHT_JOIN table2 STRAIGHT_JOIN table3 table1会优先table2载入,table2会优先table3
5 STRAIGHT_JOIN 并不改写sql表本身的条件书写顺序