zoukankan      html  css  js  c++  java
  • MySQL索引失效问题总结

    先来思考一个小问题。

    问题:当查询条件为2个及2个以上时,是创建多个单列索引还是创建一个联合索引好呢?它们之间的区别是什么?哪个效率高呢?

    先来建立一些单列索引进行测试:

    这里建立了一张表,里面建立了三个单列索引userId,mobile,billMonth。

    然后进行多列查询。

    explain select * from `t_mobilesms_11` where userid = '1' and mobile = '13504679876' and billMonth = '1998-03'

    我们发现查询时只用到了userid这一个单列索引,这是为什么呢?因为这取决于MySQL优化器的优化策略。

    当多条件联合查询时,优化器会评估哪个条件的索引效率高,它会选择最佳的索引去使用。也就是说,此处三个索引列都可能被用到,只不过优化器判断只需要使用userid这一个索引就能完成本次查询,故最终explain展示的key为userid。

    4.1 总结

    多个单列索引在多条件查询时优化器会选择最优索引策略,可能只用一个索引,也可能将多个索引都用上。

    但是多个单列索引底层会建立多个B+索引树,比较占用空间,也会浪费搜索效率
    所以多条件联合查询时最好建联合索引。

    那联合索引就可以三个条件都用到了吗?会出现索引失效的问题吗?

    4.2 联合索引失效问题

    一张图搞懂MySQL的索引失效

    1)违反最左匹配原则

    最左匹配原则:最左优先,以最左边的为起点任何连续的索引都能匹配上,如不连续,则匹配不上。

    如:建立索引为(a,b)的联合索引,那么只查 where b = 2 则不生效。换句话说:如果建立的索引是(a,b,c),也只有(a),(a,b),(a,b,c)三种查询可以生效。

    这里跳过了最左的name字段进行查询,发现索引失效了。

    遇到范围查询(>、<、between、like)就会停止匹配。

    比如:a= 1 and b = 2 and c>3 and d =4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,因为c字段是一个范围查询,它之后的字段会停止匹配。

    2)在索引列上做任何操作

    如计算、函数、(手动或自动)类型转换等操作,会导致索引失效而进行全表扫描。

    explain select * from user where left(name,3) = 'zhangsan' and age =20

    这里对name字段进行了left函数操作,导致索引失效。

    3)使用不等于(!= 、<>)

    explain select * from user where age != 20;
    explain select * from user where age <> 20;

    4)like中以通配符开头('%abc')

    索引失效

    explain select * from user where name like ‘%zhangsan’;

    索引生效

    explain select * from user where name like ‘zhangsan%’;

    5)字符串不加单引号索引失效

    explain select * from user where name = 2000;

    6)or连接索引失效

    explain select * from user where name = ‘2000’ or age = 20 or pos =‘cxy’;

    7)order by

    正常(索引参与了排序),没有违反最左匹配原则。

    explain select * from user where name = 'zhangsan' and age = 20 order by age,pos;

    违反最左前缀法则,导致额外的文件排序(会降低性能)。

    explain select name,age from user where name = 'zhangsan' order by pos;

    8)group by

    正常(索引参与了排序)。

    explain select name,age from user where name = 'zhangsan' group by age;

    违反最左前缀法则,导致产生临时表(会降低性能)。

    explain select name,age from user where name = 'zhangsan' group by pos,age;
  • 相关阅读:
    RepositoryItemComboBox 用法1
    php 直接获取url参数赋值成变量。省去繁琐的获取参数,再一个个赋值
    什么是经验,就是解决问题的能力!!
    win7 上运行 php7 +
    win2008 server 多IP配置
    mysqlli 的基本用法
    PHP操作mongoDB 笔记
    关于PHP程序员技术职业生涯规划 转自 韩天锋
    linux 简单笔记
    ubantu 重启mysql
  • 原文地址:https://www.cnblogs.com/aitree/p/14465231.html
Copyright © 2011-2022 走看看