zoukankan      html  css  js  c++  java
  • 索引失效

    • where 条件中包含 or 时,可能会导致索引失效
      • 尽量避免使用 or 语句,可以根据情况使用 union in 等来代替,这两个语句的执行效率也比 or
      • 不同版本 MySQL,关于 or 走索引情况不一致,需要具体分析
      • MySQL 5.7 版本中,当 or 两边都是单列索引,索引生效
    • where 语句中索引列使用了负向查询,可能会导致索引失效
      • 负向查询包括:NOT!=<>!<!>NOT INNOT LIKE
      • 其中负向查询并不绝对会索引失效,这要看优化器判断,全表扫描或者走索引哪个成本低了
    • 索引字段可以为 null,使用 is null is not null,可能会导致索引失效
      • null 的列使索引/索引统计/值比较更加复杂,对 MySQL 来说更难优化
      • null MySQL 内部需要特殊处理,增加数据库处理记录的复杂性,同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多
      • null 值需要更多的存储空间,无论是表中还是索引中每行中的 null 的列都需要额外的空间来标识
      • null 的处理,只能采用 is null is not null,而不能使用 =、in、<、<>、!=、not in 这些符号操作
    • 在索引列上使用内置函数,一定会导致索引失效
      • 建议尽量在应用程序中进行计算和转换
    • 隐式类型转换导致的索引失效
      • 索引列 user_id 为 varchar 类型,不会命中索引,因为 MySQL 做了隐式类型转换,调用函数将 user_id 做了转换
      • select * from `user` where user_id= 12;
      • select * from `user` where CAST(user_id AS signed int) = 12;
    • 隐式字符编码转换导致的索引失效
      • 当两个表之间做关联查询时,如果两个表中关联的字段字符编码不一致的话,MySQL 可能会调用 CONVERT 函数,将不同的字符编码进行隐式转换从而达到统一;作用到关联的字段时,就会导致索引失效
      • Demo : select l.operator from `trade_log` l, `trade_detail` d where d.tradeid = l.tradeid and d.id = 4;
        • 其中 d.tradeid 字符编码为 utf8,而 l.tradeid 的字符编码是 utf8mb4
        • 因为 utf8mb4 utf8 的超集,所以 MySQL 在做转换时会用 CONVERT utf8 转成 utf8mb4;简单来看,就是 CONVERT 作用到了 d.tradeid 上,因此索引失效
      • Suggest :
        • 将关联的字段的字符编码统一
        • 若无法统一字符编码时,手动将 CONVERT 函数作用于关联式 = 的右侧,起到字符编码统一的目的;这里是强制将 utf8mb4 转为 utf8,注意:从超集向子集转换是有数据截断的风险的
          • select l.operator from `trade_log` l, `trade_detail` d where d.tradeid = CONVERT(l.tradeid USING utf8) and d.id = 4;
    • 对索引列进行运算,一定会导致索引失效
      • 运算符如:+、-、*、/ 等
      • Demo : select * from `user` where age - 1 = 10;
      • Suggest : 优化,将运算放在值上,或者在应用程序中算好
        • select * from `user` where age = 10 - 1;
    • like 通配符可能会导致索引失效
      • % 开头,索引失效
      • Suggest :
        • 去掉开头的 %
          • select * from `user` where `name` like '%';
        • 利用覆盖索引来名中索引
          • select name from `user` where `name` like '%%';

               

         

         

         

    • 联合索引中,违背最左匹配原则,一定会导致索引失效
    • MySQL 优化器的最终选择,不走索引
      • 即使完全符合索引生效的场景,考虑到实际数据量等原因,最终是否使用索引还要看 MySQL 优化器的判断;也可以在 SQL 中强制表明走哪个索引

       

    优化索引的建议:

    • 禁止在更新十分频繁,区分度不高的属性上建立索引
      • 更新会变更 B+树,更新频繁的字段建立索引会大大降低数据库性能
      • "性别"这种区分度不大的属性,建立索引是没有意义的,不能有效过滤数据,性能和全表扫描类似
    • 建立联合索引,必须把区分度高的字段放在前面
  • 相关阅读:
    26 转义符 re模块 方法 random模块 collection模块的Counter方法
    25 正则表达式
    24 from 模块 import 名字
    24 from 模块 import 名字
    24 from 模块 import 名字
    23 析构方法 items系列 hash方法 eq方法
    21 isinstance issubclass 反射 _str_ _new_ _len_ _call_
    20 属性, 类方法, 静态方法. python2与python3的区别.
    python(1)
    python之字符串格式化
  • 原文地址:https://www.cnblogs.com/sebastian-tyd/p/13580165.html
Copyright © 2011-2022 走看看