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

    MySQL常见索引失效

    • 索引失效的原因有很多种, 这里列举一些常见失效案例。

    • 首先创建表和数据

      create table staffs(
      id int primary key auto_increment,
      name varchar(24) not null default '' comment '姓名',
      age int not null default 0 comment '年龄',
      pos varchar(20) not null default '' comment '职位',
      add_time timestamp not null default current_timestamp comment '入职时间'
      ) charset utf8 comment '员工登记表';
      
      
      insert into staffs(name,age,pos,add_time)values('z3',22,'manager',now());
      insert into staffs(name,age,pos,add_time)values('July',23,'dev',now());
      insert into staffs(name,age,pos,add_time)values('tom',23,'dev',now());
      ...
      

      添加索引:

      # 添加复合索引 name,age,pos
      alter table staffs add index idx_staffs_nameAgePos(name,age,pos);
      

    1.单个--多个索引匹配

    伴随where后面查询精度越大,key_len越大,ref中const越多,代价也会越大。
    

    2.未遵循最左前缀原则

    建立索引顺序是name,age,pos,直接查询age,未遵循最左前缀中开头必为建立索引的字段。从而导致索引失效。
    

    上面只引用了部分索引,从key_len可以看出,并且ref就一个常量,违背了最左前缀的中间部分不能省,导致只右部分索引起效
    

    3.不要在索引列上做任何操作

    • 所说的操作指的是计算,函数,自动或手动的类型转换,这样会导致索引失效,从而转换全表扫描

    使用left函数,导致索引失效
    

    4.范围检索也会让索引失效

    因为第二个字段使用范围查找,导致第二个索引用途不是检索而是排序,这样导致第三个索引失效。
    
    • 常用范围查找有:in/like/between/</>

    5.尽量使用覆盖索引

    1和2执行计划对比,可以看第二个Extra使用Using where,Using index,这样表示用索引检索并查询。
    而3,4对比可以看出虽然第三个执行计划的第二个索引字段使用age>25的范围排序,最起码第一个索引是生效的。
    
    这都是得益于select 索引字段,而不是select *
    

    6.使用不等于(!= or <>) 无法使用索引

    • 使用不等于导致全表扫描

    可以看到type=ALL为全表扫描
    

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

    • 为了避免此类事情发生最好设置default值

    8. like 以通配符开头"%abc" 会造成全表扫描

    而通过常量开头不会导致索引失效

    • 当然如果你执意像要通配符形式为%abc%形式让索引不失效也是可以的:
    • 创建表和数据,示例:
    create table `tbl_user`(
    `id` int(10) not null auto_increment,
    `name` varchar(20) default null,
    `age` int(11) default null,
    `email` varchar(20) default null,
    primary key(`id`)
    )engine=innodb auto_increment=1 default charset=utf8;
    
    insert into tbl_user(name,age,email)values('1aa1',21,'aaa@163.com');
    insert into tbl_user(name,age,email)values('2aa2',22222,'bbb@163.com');
    insert into tbl_user(name,age,email)values('3aa3',33333,'ccc@163.com');
    
    • 创建覆盖索引:
    create index idx_user_nameAge on tbl_user(name,age);
    
    • 我们可以看到给name,age创建覆盖索引

    我们指定查询的字段使用覆盖索引全,单字段,都不会造成索引失效
    

    但我们添加email(email不是我们创建索引字段),就会造成全表扫描,email就好像搅屎棍一样,导致索引失效
    

    所以通过:select [覆盖索引or 主键索引 or 覆盖索引沾边的字段] from staffs where name like '%July%';可以不会让索引失效,通常type为index

    9.字段不是整形不加单引号

    • 字符串不加单引号索引失效 name为varchar类型 ,必须使用单引号。 否则会失效。

    name字段类型为varchar,但是我们查询条件为整型,其内部SQL会自行将int类型转换字符串,但是索引失效
    

    10.少用or

    • 用它连接也会导致索引失效。
  • 相关阅读:
    telnet和ssh
    sersync实现实时同步
    rsync服务端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(非源码)
    centos 建立Clamav自动扫描脚本
    DELL T110II Server如何通过RAID 级别迁移的方式在OMSA下实现磁盘阵列扩容?
    Dell PowerEdgeServerT110II USB Boot更新
    Centos7最小安装下Install Clamav(2017-06-09最后更新)
    Centos7 samba 匿名共享 简单config
  • 原文地址:https://www.cnblogs.com/xujunkai/p/12492737.html
Copyright © 2011-2022 走看看