mysql高级_04_索引优化案例分析

mysql高级_04_索引优化案例分析

      • 避免索引失效
    • 2. 优化查询
      • 2.1 小表驱动大表
      • 2.2 ORDER BY / GROUP BY
      • 2.3 Mysql慢查询日志


  • 单表:复合索引 范围以后的索引会失效
  • 两个表: 左连接 索引应建在右表,右链接,索引在左表
  • Join
    • 尽可能减少Join 语句中 的循环总次数,永远用小结果集驱动大结果集
    • 优先优化 内层循环
    • 保证Join语句中被驱动表上Join条件字段已经被索引
    • 当无法保证被索引且内存资源充足的前提下,不要太吝啬JoinBuffer

避免索引失效

  • 最佳左前缀法则
    • 如果索引了多列,要遵守最左前缀法则;
    • 指的是 查询从索引的最左前列开始并且不跳过索引中的列
  • 不要在索引列上做任何操作
    -(计算、函数(自动or手动)类型转换) ,会导致索引失效而转向全部表扫描
  • 存储引擎不能使用索引中范围条件右边的列 (范围之后全部失效
  • 尽量使用覆盖索引
    • 只访问索引的查询(索引列于查询列一致)
    • 减少 SELECT *
  • mysql 在使用不等于(!= 或者<>)的时候无法使用索引,会导致全表扫描
  • is null、 is not null 也无法使用索引
  • like 以通配符开头 如(’%aaa’),索引会失效
    • 可以使用 覆盖索引 从 ALL 升到 INDEX
  • 字符串不加单引号索引失效
  • 少用 OR 用它来连接时索引失效

mysql高级_04_索引优化案例分析_第1张图片

2. 优化查询


2.1 小表驱动大表

  • 永远小表驱动大表
  • IN 和 EXISTS 的区别
  • IN 一直查找,EXISTS 遇到则立马返回(只返回 true 或者 false, 所以 和select 后面的字段无关 ,子查询完全可以写成 SELECT 1 FROM t)
#如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in: 
#例如:表A(小表),表B(大表)
select * from A where cc in (select cc from B) ;//  效率低,用到了A表上cc列的索引;
select * from A where exists(select 1 from B where cc=A.cc) ;// 效率高,用到了B表上cc列的索引。 
#相反的
select * from B where cc in (select cc from A) ; //效率高,用到了B表上cc列的索引;
select * from B where exists(select 1 from A where cc=B.cc) ;//效率低,用到了A表上cc列的索引。

2.2 ORDER BY / GROUP BY

  • ORDER BY
  • ORDER BY 子句尽量使用Index方式排序,避免使用FileSort方式排序,尽可能在索引列上外城排序操作,遵照索引键的最佳左前缀。如果不在索引列上,FileSort有两种算法,Mysql就要启动双路排序和单路排序。
  • 什么是双路排序和单路排序?
    • 双路排序:Mysql4.1之前是使用双路排序,字面的意思就是两次扫描磁盘,最终得到数据,读取行指针和ORDER BY列,对他们进行排序,然后扫描已经排好序的列表,按照列表中的值重新从列表中读取对数据输出。也就是从磁盘读取排序字段,在buffer进行排序,再从磁盘读取其他字段。文件的磁盘IO非常耗时的,所以在Mysql4.1之后,出现了第二种算法,就是单路排序。
    • 单路排序:从磁盘读取查询所需要的所有列,按照ORDER BY在buffer对它进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为它把每一行都保存在了内存里。
  • 但是,问题来了,有可能单路排序算法一次拿不出数据,那么就还比双路排序更消耗IO,效率更慢!
  • 提高ORDER BY速度的技巧
    • 1:ORDER BY时不要使用SELECT *,只查需要的字段。
      • a:当查询的字段大小综合小于max_length_for_sort_data而且排序字段不是TEXT|BLOB类型时,会用改进后的算法—单路排序,否则用老算法—多路排序。假设只需要查10个字段,但是SELECT *会查80个字段,那么就容易把sort_buffer缓冲区用满。
      • b:两种算法的数据都有可能超出sort_buffer的容量,超出之后,会创建tmp文件进行合并排序,导致多次I/O,但是用单路排序算法的风险会更大一些,所以要提高sort_buffer_size大小。
    • 2:增大sort_buffer_size参数大小
      不管用哪种算法,提高这个参数都会提高效率。当然要根据系统能力去提高,因为这个参数是针对每个进程的。
    • 3:增大max_length_for_sort_data参数大小
      提高这个参数,会增加用改进算法的概率。但是如果设的太高,数据总量超出sort_buffer_size的概率就增大,明显症状是高的磁盘I/O活动和低的处理器使用率。
  • GROUP BY的优化
  • GROUP BY实质上是先排序后进行分组,遵照索引的最佳左前缀。
  • 当无法使用索隐裂,考虑增大max_length_for_sort_data和sort_buffer_size的参数设置。
  • WHERE 高于 HAVING,能写在WHERE限定的条件就不要去HAVING限定了。

2.3 Mysql慢查询日志

  • Mysql的查询讯日志是Mysql提供的一种日志记录,它用来记录在Mysql中响应时间超过阈值的语句,具体指运行时间超过long_query_time值得SQL,则会被记录到慢查询日志中。
  • long_query_time的默认为10,意识是运行10秒以上的语句。由它来看那些SQL语句超出了我们的最大忍耐值,比如一条SQL执行超过了5秒,我们就算慢查询,我们就可以结合Explain进行分析。
  • 默认Mysql没有开启慢查询,需要我们说动设置这个参数。当然,如果不是调优需要的话,一般不建议开启该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志写入文件。
  • 查看是否开启:show global like ‘%slow_query_log%’;
  • 开启:set global slow_query_log = 1; //设置开启或者关闭,0为关闭,1为开启
  • 具体设置时间:https://www.cnblogs.com/wt645631686/p/8321498.html

mysql提供的日志分析工具–mysqldumpslow

  • 具体也是上面的链接

你可能感兴趣的:(数据库)