1.参考
MySQL实战—— Limit与Order by 对查询效率的巨大影响
https://blog.csdn.net/zhibo_lv/article/details/117846795
视频:尚硅谷MySQL数据库高级(bilibili收藏)
2.索引
2.1引入
2.1.1SQL执行慢的原因
1)Sql写的烂
2)索引没建好
3)表设计不好,导致join过多
4)服务器调优和参数设置不合理
2.1.2.sql写的顺序和机读顺序
1)写的顺序
2)机读顺序
2.2基本概念
1)索引是帮助mysql快速查找数据的数据结构
2)不真删除数据,而往往采用假删除的原因:
a.保留数据,业务不用,可以做分析用
b.频繁删除数据,会导致索引失效
c.删除数据会导致出现间隙,引发间隙锁,降低执行效率
3)索引本身也很大,往往以文件的形式存在磁盘
4)索引的数据结构是BTree结构(多路搜索树),其中,聚集索引、次要所以、唯一索引、复合索引、覆盖索引用的是B+树
2.3索引的优势劣势
1)优势:
提高了查询效率,减少了数据库IO成本
提高了排序效率,降低了CPU消耗
提高并发能力,mysql的InnoDB引擎可以添加行锁,行锁是基于索引的,因此可以提高并发能力
2)劣势
索引也是一张表,保存了主键、索引字段,并指向实体表记录(指针),占用空间;
索引虽然提高查询效率,但是会降低更新表的速度,因为维护数据的同时也要维护对应索引
2.4索引的分类
1)单值索引:只包含一个列的索引
2)唯一索引:索引字段的值不重复,但允许空值
3)复合索引:包含多个列
2.5索引的结构与检索原理
1)3层b+树可以表示上百万条数据,定位到数据只发生3次IO,不需要每条数据都IO,性能极大提升
2)真实数据存在叶子节点,如3、5、9、10都是真实数据
3)非叶子节点不存真实数据,只存某种导向信息,如17、35不真实存在于数据表中
2.6适合、不适合建索引的条件
1)适合的:
主键自动建唯一索引
频繁作为查询条件的字段
外键建立索引
2)不适合的
频繁更新的字段
where用不到的字段
高并发下单值索引还是复合索引?---复合索引更好
经常增删改的表不建索引
数据量少的表不建索引
字段值少的(例如枚举)不建索引
2.7单表、双表、三表建索引
单表:在where和orderby的字段上建索引
双表:左联在右表关联字段上建索引,右联在左表关联字段上建索引
三表:同双表经验
2.8建索引注意点:
1)全值匹配最爱:复合索引,查询条件字段与索引字段、顺序都对应;
2)最左匹配原则:(参考:https://blog.csdn.net/zhouchen1998/article/details/124672991)
index_abc:(a, b, c) //相当于同时有了(a)、(a, b)、(a, b, c)索引
select * from table where a = 'aa' and b ='bb' and c='cc'; //最好,全值匹配
select * from table where c='cc' and b='bb' and a='aa'; //也生效,因为查询优化器会调整顺序,仅有==和in可以顺序随意
select * from table where c='cc' and b='bb'; //索引失效,最左匹配不上
3)不在索引列上做做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效
4)索引,不能使用查询条件为范围的后面的字段
select * from table where a='aa' and b>'bb' and c='cc'; //c失效,b是范围查找后面就失效,大于、小于、between、in、like
//a用于查找,b用于排序,c失效
5)尽量使用覆盖索引(索引字段全覆盖查询字段),减少select*,
select a,c,b from table where c='cc' and b='bb'; //索引生效,因为查询内容覆盖索引,查找索引树,而不是全表搜索
6)使用!=、>、<,会导致索引失效,全表查询
7)is null、is not null也无法使用索引
8)like百分号加右边
select * from table where a like '%aa%'; //索引失效
select * from table where a like '%aa'; //索引失效
select * from table where a like 'aa%'; //可以使用索引
9)like百分号不能加右边,但是还不想索引失效
select a,b,c from table where a like '%aa%'; //全覆盖索引,使用索引
10)字符串不加单引号,索引失效
select * from table where a = 'aa'; //索引生效
select * from table where a = aa; //能查出来,优化器执行类型转换。索引失效,隐式的类型转换导致
11)少用or,用它会导致索引失效
select * from table where a = 'aa1' or 'aa2'; //索引失效
3.sql查询优化
3.1分析步骤
1)观察、测试,至少跑1天,看看生产的慢sql情况
2.开启慢查询日志,并设置阙值,比如执行超过5s的就是慢查询,并把它抓取出来
3.explain+慢sql分析
4.show profile //查看sql在mysql服务器里的执行细节和生命周期情况
5.运维经理orDBA,进行sql数据库服务器的参数调优
3.2查询优化
3.2.1小表驱动大表:减少io连接次数,io连接也消耗性能
1)类比解释:外层次数少,内层次数多
for(i=0;i<5;...){
for(j=0;j<1000;...){}
}
2)in和exist:exist是in的变种写法,一般用in,变种可以贴合小表驱动大表原则
select * from A where bid in (select id from B) //先执行子查询,如果B数据量小,此时用in非常合适
select * from A where exist(select '随便' from B where B.id=A.bid) //将主查询的数据放到子查询中做验证,先执行煮茶询,如果A中数据量小,此时用exist非常合适
3.2.2使用索引优化order by
1)mysql支持两种方式的排序,index和filesort;index效率高,它指mysql扫描索引完成排序;filesort效率低
2)order by 满足两种情况,使用index排序:index_abc:(a, b, c)
a)order by 后的字段遵循最左匹配原则
select * from table where a>'aa' order by a,b,c; //using index,order by遵循最左匹配
select * from table where a>'aa' order by c,b; //using filesort,order by不遵循最左匹配
b)where 与order by条件列组合满足最左匹配原则
select * from table where a='aa' order by b,c; //using index,where与order by组合遵循最左匹配
select * from table where a>'aa' order by b,c; //using filesort
select * from table where a='aa' and b='bb' order by c; //using index
select * from table where a='aa' and b>'bb' order by b,c; //using index,where里面b>,但是order by续上了,也行
3.2.2使用索引优化group by
group by实质是先排序后分组,适用于order by的以上原则,同样适用于group by
3.2.3慢查询日志
1)默认关闭,需要主动开启,开启慢查询日志会消耗数据库性能
2)可以使用分析工具