• mysql 查询优化案例汇总


    一 简介:此文章为经历过的sql案例集合和相关思路

    二 案例1:

       现象: 测试环境出现select语句,join2张表多次join,explain结果如下 出现 using where,using join buffer (Block Nested Loop)

       思路分析:BNL 5.6优化,首先就看连接字段是否有索引(也有可能有索引没加上),发现没有索引

       解决办法: 连接字段加上索引,问题解决(是不是很简单)

       案例2 

       现象:线上出现select并发语句,语句比较复杂,就不贴出来了

       思路分析:explain下发现多个join后面的连接字段没有索引

       解决办法:连接字段加上索引,问题解决 

       案例3
        select * from a where ctime <= DATE_FORMAT(DATE_ADD(SYSDATE(), INTERVAL - 30 DAY), '%Y-%m-%d')  
        现象: 此语句全表扫描
        思路分析: 很奇怪的语句,ctime有索引,而且函数并没有作用于索引本身,为什么不走索引呢,尝试用字符串日期代替函数本身,explain下是走索引的,问题出现在函数这块
        解决办法: 将sysdate去掉,用now取代,explain下发现,已经走索引
       补充
        sysdate和now的区别
       1 select sysdate(),sleep(2),sysdate() select now(),sleep(2),now()
          SYSDATE获取当时实时的时间,在语句执行中是不断变化
          NOW()取的是语句开始执行的时间,在整个语句执行过程中都不会变化。
       2 sysdate在函数计算中不走索引,now可以走索引,前提这个时间字段本身是索引项

       3 选择sysdate可能导致主从同步问题

        建议 在mysql语句中建议采用now函数

      案例 4

         select * from  table  where  id  in ( id1 ,id 2,。。。)

      现象  查询很慢,id存在索引,但是并没有走

      思路分析:由于此表数据量大,可能存在因为数据量导致的索引失效问题,所以采用 force index进行尝试

      解决办法: 采用force index方式进行查询

      补充: explain下的force index出现了失真,扫描行数居然是表数据量的几倍,暂时没找到原因,所以,不要过分依赖explain的结果,自己去查询试试

     案例5 

         select * from table where a='' order by b 

     现象 已经建立了 a和b的联合索引,依然出现了file sort文件排序

     思路分析: 调出表结构发现 a varchar(200) b varchar(300),远远超过了5.6规定的767字节,那为什么还能建立成功呢,原来5.7已经放开了限制,已经调大到3000+.但是依然只能用到前缀索引

     解决办法: 缩短字段长度,尽量索引长度不要超过767字符

     补充: 5.7虽然放开了索引长度的限制,但是毫无意义,也请大家尽量规范好字符串的长度,防止发生上述问题

     案例6 

        select * from table where a= b= order by c

     现象 已经建立了 a c 联合索引 ,但是效率很低

    思路分析: 首先通过explain发现,扫描行数并不多 也就3W多行,但是令人奇怪的是,建立了a c联合的索引,却只用到了a,而且extra中并没有出现文件排序

    解决方法: 建立 a b c三者的联合索引。

    总结:不要单单看扫描行数少就认为不要优化,让sql走正确的索引,去掉不正确的,这也是一个非常重要的原则

     案例7 

      select * from table  where a in () and b > ' ' order by b desc 

      索引情况   (a b) (b a)  联合索引

       explain情况  走了(b a)的索引 但是只是走了部分没有走完全,而且extra没有文件排序

       分析 大概可知执行顺序 是先进行了索引排序 范围取值 然后导致联合索引中断,去掉order by发现就走了(a,b)联合索引,这是典型的由于排序导致的索引的错误选择

      解决方法 改写sql   select * from (select * from table where a in () and b >'')  t order by t,b desc  将排序放在外循环即可

     案例8

       select  injer join  injer join  injer join group by  order by  limit 10 ,20

       分析 根据expain分析  扫描行数只有2千行,但是执行用了2min,既然不能依赖explain 就定位哪里出了问题.

               1  先去掉 group by order by   执行 结果速度一样,证明不是分组排序导致

               2  先执行第一个injer join   记录时常

              3  再 加入一个injer join  再记录时常

              最后发现 每加一个injer join表 执行时间就耗时增加一倍,这样问题就好定位了

        解决方法  将第一个injer join改成 in ()  速度比之前快了很多,

        总结  1 减少join的次数,用in代替  2 当explain无法分析出原因的时候 要手动进行排查定位

      

  • 相关阅读:
    自动封箱和拆箱
    关于Java的一道内存的题目
    volatile关键字
    阶乘尾零
    Java之final的解析
    从1到n整数中1出现的次数
    最小安装雷达数量
    二叉树重建
    最短路径—Dijkstra算法
    PAT A1063——set的常见用法详解
  • 原文地址:https://www.cnblogs.com/danhuangpai/p/8422650.html
Copyright © 2020-2023  润新知