8.索引优化

索引失效

1.最佳左前缀原则: 如果索引了多列,要遵守最佳左前缀法则,指的是查询从索引的最左列开始,并且不跳过索引中的列.
     如给表创建复合索引:create index on 表名(name,age,poit)
     1.不会使用索引,具体情况参考:https://www.cnblogs.com/rjzheng/p/12557314.html,因为mysql底层使用b+数作为索引的数据结构
       如果多列,会按照第一列排序,第一列相同的情况下再按照二列排序..,整体上2列并不是有序的  
         select * from user where age='18';
     
     2.也不会用到索引
         selec * from user where poit=15;
     
     3.也不会用到索引
         selet * form user where age=18 and ponit=15;
     
     4.会使用索引
         select * from user where age=19 and name='吴孟达';
         mysql优化器会优化sql语句为:和索引的顺序相同
         select * from user where  name='吴孟达' and age=19;
     
     5.name只用到了索引,point并没用到
         select * from user where name='吴孟达' and point=15;
     
 2.不在索引列上做任何操作(计算/函数/(自动or手动)类型转换),会导致索引失效而转向全表扫描
 3.存储引擎不能使用索引中范围条件右边的列
     select * from user where name='july' and age >25  and pos='manager';
     只有name 和age用到索引,但是pos没有用到,因为age是范围查找,右边的失效
 
 4.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
     如select name,age,poit from user;  
 5.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
 6.is null,is not null也无法使用索引
 7.like以通配符开头('%abc')mysql索引失效会变成全表扫描的操作
     如下图:
         1.%放左边索引会失效
         2.%放右边索引才会生效
     那如果想使用 like '%%'双百分号,又想索引生效应该如何操作呢??
     答案:使用覆盖索引:
         即:查询的字段在创建的索引列表中,如
         1.创建了复合索引(name,age,point)
         
         2.是可以用到索引的
             select name from user where name like '%吴孟达%'
             select 任何在索引列表中的字段 where name like '%吴孟达%';
         3.但当查询的字段超出覆盖索引范围:
             如:用不到索引了
                 1.select * from user where name like '%吴孟达%'
                 2.select name,age,point,多余字段 from user where name like '%吴孟达%'
 9.字符串不加单引号索引失效
 10.少用or,用它连接会失效
 11.一般order by是给定个范围,group by基本上都要进行排序,会有临时表的产生

查询截取分析

分析步骤:
    1.观察,至少跑一天,看看生产的慢sql情况
    2.开启慢查询日志,设置阈值,比如超过5秒钟的就是慢sql,并将他们抓取出来
    3.explain+慢sql分析
    4.show profile;查询sql在mysql服务器中的执行细节和声明周期情况
    5.进行sql数据库服务器的参数调优
    


查询优化:
    1.永远小表驱动大表

order by 排序优化

order by子句
    1.尽量使用index方式排序,避免使用FileSort方式排序
    2.尽可能在索引列上完成排序操作,最招索引建的最佳左前缀
    3.mysql支持两种方式的排序,fileSort和index,index效率高,它指mysql扫描索引本身完成排序,filesort方式效率较低
    4.order by满足两种情况,会使用index方式排序:
        4.1order by语句使用索引最左前列
        4.2使用where子句与order by子句条件列组合满足索引最左列
    5.如果不在索引列上,filesort有两种算法,mysql就要启动双路排序和单路排序
        1.双路排序(mysql4.1之前):取一批数据,要对磁盘进行两次扫描,I\O很耗
                1.从磁盘中读取排序字段,在buffer中进行排序,2.再从磁盘中读取其他字段
        2.单路排序(mysql4.1之后):
            从磁盘读取查询所需要的的列,按照order by列在buffer对他们进行排序,然后扫描排序后的列表进行输出
            他的效率会更快一点,避免了第二次读取数据,并且把随机IO变成了顺序ID,但是他会使用更多的空间
            因为它每一行都保存在内存中
            
        单路排序引申出的问题:在sort_buffer中,单路排序要比多路排序占用更多的空间,因为单路排序是把所有字段都取出放入内存中,
        数据总大小可能超过sort_buffer的容量,导致每次只能读取sort_buffer容量大小的数据,进行排序(创建tmp文件,多路合并),排完再
        取sort_buffer容量大小,再排...从而进行多次I/O.
        本想省一次I/O操作,反而导致了大量的I/O操作,反而得不偿失

group by(和order by的规则一致)

1.group by实质是先排序后进行分组,遵照索引建的最佳左前缀
2.无法使用索引列,增大max_length_for _sort_data参数+增大sort_Buffer_size参数的设置
3.where高于having,能写where限定条件就不要去having去限定了

mysql慢查询

默认情况下,mysql数据库没有开启慢查询日志,需要我们手动设置这个参数

如果不是调优需要的话,一般不建议启动这个参数,因为开启慢查询日志会或多或少带来一定性能的影响,慢查询日志支持将日志记录写入文件

1.如何查看慢查询日志设置:
    show VARIABLES like '%slow_query%'
2.打开慢查询
    set flobal slow_query_log=1;
    这么设置只针对当前数据库生效,数据库重启后失效

查看超过慢查询时间阈值的sql数:
show global status like '%Slow_queries%'

日志分析工具:mysqldumpslow

1.s:表示以何种方式进行排序
2.c:访问次数
3.l:锁定时间
4.r:返回记录
5.t:查询时间
6.al:平均锁定时间
7.ar:平均返回记录数
8.at:平均查询时间
9.t:即为返回前面多少条数据
10.g:后面搭配一个正则匹配模式,大小写不敏感

show profile

是mysql提供可以用来分析当前会话中语句执行的资源消耗情况,可以用于sql调优的测量
默认情况下,参数处于关闭状态,并保存最近15次的运行结果
1.查看profile状态:
    show VARIABLES like 'profiling';
2.诊断sql
    1.show profiles;查看查询过的sql和对应的id号
    2.show profile cpu,block io for query id号;根据1的id号查询该条记录的详细执行耗时信息
        如果2的查询结果中出现下面四种:就危险了...
            1.converting HEAP to MyISAM:查询结果太大,内存不够用往磁盘上搬了
           2.Creating tmp table:创建临时表
               拷贝数据到临时表
               用完再删除
           3.Copying to tmp table on disk 把内存中临时表复制到磁盘,危险!!!
           4.locked 

全局查询日志

只能测试环境用,不能生产环境用!

posted @ 2022-05-25 21:02  努力的达子  阅读(46)  评论(0编辑  收藏  举报