• 8.索引优化


    索引分析

    1.单表的优化:

      上面的注释已经提到了 BTree 索引的工作原理,在一个联合索引中,按照创建索引时的字段的顺序,来为其进行排序

      select a,b from t1 where x = 1 and y > 1 order by z ;联合索引为(x,y,z),x,z给出了一个确切的值,y给出的是一个范围,

      我们 explain它,会有 using filesort,这是因为 y > 1条件是一个范围值,虽然也会用到索引,用到的是索引的排序,而不是查询。

      而且因为y的值给得不准确,y确定不了,就找不到z,所以z不会用到索引,要通过z去排序,又没有索引用,所以MySQL 只能自己进行文件内排序filesort

    2.多表的优化(Join 语句的优化)

      1.尽可能减少Join语句中的 NestedLoop的循环总次数:"永远用小结果集驱动大的结果集"  

      2.优先优化NestedLoop的内层循环

      3.保证Join语句中被驱动表上的Join条件字段已经被索引

      4.当无法保证被驱动表的Join条件字段被索引且内存资源充足的前提下,不要太吝啬 JoinBuffer的设置

      如:select * from class left join book on class .card =book.card left join phone on book.card = phone.card,

      因为这条select的执行顺序是,先查询class表,再查询book,再查询phone

      这是一个 三表连接,按照上面的原则,class表应该是最小的,phone 表应该是最大的,用class 去驱动 book,用book驱动phone,

      而且需为被驱动的表上的join条件字段添加索引,

      原理:这里是left join,需为右边那张表的连接字段添加索引,因为左连接 左边那张表应该全部包含进来,右边那张表只进来重合的那部分,

      即右边有的,左边一定有,这样的话,右边为公共区域,更加关键,所以一定要为右边建立索引,这里就是要为book.card 和 phone.card 建立

    索引失效(如何避免)

    要实验的话,select 后面的 字段需要不满足 覆盖索引,不然的话,索引不会失效,还是会用到覆盖索引

      1.全值匹配我最爱

      2.最佳左前缀法则    如果索引了多列,要遵循最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列

      (是where 后面字段的顺序需遵循,和select 后面的字段无关,select 后面的字段只会影响该索引是否为覆盖索引)

      3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

      4.存储引擎不能使用索引中范围条件右边的列

      5.尽量使用 覆盖索引(只访问索引的查询(索引列和查询列一致)减少 select *)

      6.mysql 在使用 不等于(!=或者<>)的时候无法使用索引,会导致全表扫描

      7.使用is null,is not null 也无法使用索引

      8.like 以通配符开头('%abc...')mysql 索引失效会变成全表扫描的操作

        原因分析:一开始就以 % 开头,会导致无法准确定位,无法通过索引找到那个值

        解决办法:1.将 % 放到后面 (不完善) 2.使用覆盖索引,(如果用到了覆盖索引,并且需要模糊查询的字段在覆盖索引中)

      9.字符串不加  ‘ ’ ,索引失效

      10.少用 or,用它来连接时索引失效

    优化口诀总结:
      全值匹配我最爱,最左前缀要遵守
      带头大哥不能死,中间兄弟不能断
      索引列上少计算,范围之后全失效
      LIKE百分写最右,覆盖索引不写 *
      不等空值还有or,索引失效要少用
      VAR引号不可丢 ,SQL高级也不难

    感觉不算特别准确,补充自己的总结

      explain select * from newslabel where name = 'CBA' and pid = 1; i      dx(pid,name)

      1.首先关于 select 后面的字段,如果建立的复合索引完全包含后面的,那么就是覆盖索引,

      这里很多案例都不会失效,因为覆盖索引没有失效

      2.where 后面的 条件,索引的第一个必须要有(pid),后面的随意,(即带头大哥不能死,中间兄弟无所谓)

      可以不按照索引建立的顺序来书写,MySQL会优化,还是会用到索引,但是最好按序写查询条件

      3.关于 order by 和 group by,必须严格按照索引建立时的顺序,即 idx(pid,name,age)前提下,必须写成

      select * from newslabel where pid = 1 and name = 'CBA'  order by age,

      (这时就是带头大哥不能死,age 和 pid之间的中间兄弟不能断)

      即age前面的被索引了的查询字段需为常量((where = ‘常量’ ),age前面的字段为常量,自然就不需要排序了),有了前面的准确位置,age才能使用index排序,不出现 filesort

      或者如果不写 where 对 使age前面的列生效的话,就必须按序写成 order by pid,name,age

      

      原因:可以参照 联合索引 BTree 的原理,因为创建树的时候就是通过第一列的值,在第一列的值相同的情况下,再对第二列进行排序放到 树中,

      所以需要通过第一列的值去检索第二列的值,

    一般性建议:

      1.对于单键索引,尽量选择针对当前 query 过滤性更好的索引

      2.在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好

      3.在选择组合索引的时候,尽量选择可以包含当前query中的 where 字句中更多字段的索引

      4.尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

  • 相关阅读:
    python获取前几天的时间
    协程
    python实现进制之间的转换
    爬虫学习博客
    python 将base64字符串还原为图片
    python进行md5加密
    初始Hibernate4
    Linux安装tomcat
    centOS7安装jdk
    centOS7安装mysql
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7366788.html
Copyright © 2020-2023  润新知