看前提问:table中有多个字段组成的联合索引(a,b,c),查询时哪些情况能够命中索引呢?

话不多说,直接开搞:

数据库表结构如下:

 CREATE TABLE `test` (
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`class_id` int(4) NOT NULL DEFAULT '' COMMENT '班级ID',
`score` int(4) NOT NULL DEFAULT '' COMMENT '学分',
`total` int(4) NOT NULL DEFAULT '' COMMENT '总计',
PRIMARY KEY (`id`),
KEY `idx_class_score_total` (`class_id`,`score`,`total`) COMMENT '测试表'
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='测试表';

可以看到:表中根据class,score,total字段建立联合索引 idx_class_score_total ,下面开始验证我们的猜想;

首先我们验证当根据一个字段查询数据的情况:

 EXPLAIN SELECT * FROM test WHERE class = 1;
 EXPLAIN SELECT * FROM test WHERE score = 1;
 EXPLAIN SELECT * FROM test WHERE total = 1;

上述结果发现:type有两种类型:ref和index;

index:这种类型表示mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个联合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。所以,上述语句会触发索引。

ref:这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。

结果:根据一个字段查询的时候实际上都可以命中索引,只不过ref效率更高,index情况效率不高;

其次我们再来验证根据任意两个字段查询的结果:

 EXPLAIN SELECT * FROM test WHERE class = 1 AND score = 1;
 EXPLAIN SELECT * FROM test WHERE class = 1 AND total = 1;
 EXPLAIN SELECT * FROM test WHERE score = 1 AND total = 1;

上述实践可得:a_b,a_c可以命中索引,b_c没有命中索引;

是不是有个问题?为什么a_c也可以命中索引?

我们仔细观察下sql1和sql2的执行结果,可以发现key_len是不一样的且ref不一样,a_c命中索引并不是全命中,只是部分命中索引,命中的是a的索引,所以key_len=4且ref=const;

最后我们看下根据三个字段一起查询的结果(包括打乱顺序);

 EXPLAIN SELECT * FROM test WHERE class = 1 AND score = 1  AND total = 1;
 EXPLAIN SELECT * FROM test WHERE total = 1 AND score = 1  AND class = 1;

上述结果发现:两条sql的执行结果是一致的,所以当根据这三个字段查询数据时都可以命中索引无论顺序;

是不是又有一个疑问?为什么打乱顺序也可以命中索引?

mysql中的查询优化器会纠正这条sql语句该以哪种顺序执行效率最高,最后生成真正的执行计划(QEP),尽量利用到索引时查询顺序效率最高。所以mysql查询优化器最终会以(a_b_c)这种顺序查询,所以b_a_c可以命中索引;

附录:

各属性含义:

  • id: 查询的序列号

  • select_type: 查询的类型,主要是区别普通查询和联合查询、子查询之类的复杂查询

    • SIMPLE:查询中不包含子查询或者UNION
    • 查询中若包含任何复杂的子部分,最外层查询则被标记为:PRIMARY
    • 在SELECT或WHERE列表中包含了子查询,该子查询被标记为:SUBQUERY
  • table: 输出的行所引用的表

  • type: 访问类型

    • ALL: 扫描全表
    • index: 扫描全部索引树
    • range: 扫描部分索引,索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询
    • ref: 使用非唯一索引或非唯一索引前缀进行的查找
    • (eq_ref和const的区别:)
    • eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
    • const, system: 单表中最多有一个匹配行,查询起来非常迅速,例如根据主键或唯一索引查询。system是const类型的特例,当查询- 的表只有一行的情况下, 使用system。
    • NULL: 不用访问表或者索引,直接就能得到结果,如select 1 from test where 1
  • key: 显示MySQL实际决定使用的索引。如果没有索引被选择,是NULL

  • key_len: 使用到索引字段的长度
    注:key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

  • ref: 显示哪个字段或常数与key一起被使用

  • rows: 这个数表示mysql要遍历多少数据才能找到,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数,在innodb上可能是不准确的

  • Extra: 执行情况的说明和描述。包含不适合在其他列中显示但十分重要的额外信息。

  • Using index:表示使用索引,如果只有 Using index,说明他没有查询到数据表,只用索引表就完成了这个查询,这个叫覆盖索引。

  • Using where:表示条件查询,如果不读取表的所有数据,或不是仅仅通过索引就可以获取所有需要的数据,则会出现 Using where。

MySql最左匹配原则解析的更多相关文章

  1. Mysql最左匹配原则实践(原创)

    mysql最左匹配原则 什么叫最左匹配原则 最左匹配原则的误区 实战 结论: 1 条件查询中条件顺序没有关系 2 在最左匹配原则中,有如下说明: 最左前缀匹配原则,非常重要的原则,mysql会一直向右 ...

  2. 3.联合索引、覆盖索引及最左匹配原则|MySQL索引学习

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 在数据检索的过程中,经常会有多个列的匹配需求,今天介绍下联合索引的使用以及最左匹配原则的案例. 最左匹配原则作用在联 ...

  3. Mysql索引最左匹配原则

    先来看个例子: 1. 示例1:假设有如下的一张表: DROP TABLE IF EXISTS testTable; CREATE TABLE testTable ( ID BIGINT NOT NUL ...

  4. Mysql中联合索引的最左匹配原则

    在Mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先. 如果我们建立了一个2列的联合索引(col1,col2),实际上已经建立了两个联合索引(col1).(col1,col2); 如果有一 ...

  5. MySQL组合索引最左匹配原则

    几个重要的概念 1.对于mysql来说,一条sql中,一个表无论其蕴含的索引有多少,但是有且只用一条. 2.对于多列索引来说(a,b,c)其相当于3个索引(a),(a,b),(a,b,c)3个索引,又 ...

  6. Mysql中联合索引的最左匹配原则(百度)

    创建联合索引时列的选择原则 经常用的列优先(最左匹配原则) 离散度高的列优先(离散度高原则) 宽度小的列优先(最少空间原则) 在Mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先.如果我们 ...

  7. MySQL 索引失效-模糊查询,最左匹配原则,OR条件等。

    索引失效 介绍 索引失效就是我们明明在查询时的条件为索引列(包括自己新建的索引),但是索引不能起效,走的是全表扫描.explain 后可查看type=ALL. 这是为什么呢? 首先介绍有以下几种情况索 ...

  8. java连接mysql数据库详细步骤解析

    java连接mysql数据库详细步骤解析      第一步:下载一个JDBC驱动包,例如我用的是:mysql-connector-java-5.1.17-bin.jar      第二步:导入下载的J ...

  9. mysql group by 用法解析(详细)

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

随机推荐

  1. 初窥Android AudioFlinger

    Android  AudioFlinger 是Android音频系统的两大服务之一,另一个服务是AudioPolicyService,这两大服务都在系统启动时有MediaSever加载,加载的代码位于 ...

  2. 使用C#开发pdf阅读器初探(基于WPF,没有使用开源库)

    前言 pdf是最流行的版式格式文件标准,已成为国际标准.pdf相关的开源软件非常多,也基本能满足日常需要了.相关商业软件更是林林总总,几乎应有尽有!似乎没必要自己再独立自主开发!但,本人基于以下考虑, ...

  3. Java设计模式二

    今天谈的是工厂模式,该模式用于封装和对对象的创建,万物皆对象,那么万物又是产品类,如一个水果厂生产三种水果罐头,我们就可以将这三种水果作为产品类,再定义一个接口用来设定对水果罐头的生成方法,在工厂类中 ...

  4. 原本准备的 event loop 分享

    基础介绍 Stack 栈 一种先入后出的数据结构. 两个基本操作: 推入,弹出 Queue 队列 一种先入先出的数据结构 操作: 入队,出队 两种任务: 同步任务,异步任务 同步任务: 在调用栈中等待 ...

  5. 位运算基础(Uva 1590,Uva 509题解)

    逻辑运算 规则 符号 与 只有1 and 1 = 1,其他均为0 & 或 只有0 or 0 = 0,其他均为1 | 非 也就是取反 ~ 异或 相异为1相同为0 ^ 同或 相同为1相异为0,c中 ...

  6. Keras深度神经网络算法模型构建【输入层、卷积层、池化层】

    一.输入层 1.用途 构建深度神经网络输入层,确定输入数据的类型和样式. 2.应用代码 input_data = Input(name='the_input', shape=(1600, 200, 1 ...

  7. 深入学习JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  8. 安装msyql报错——error: Failed dependencies

    报错原因: 1.存在两个版本的msyql-community-release. 解决方法: 1.将不要的哪个进行去除,使用命令: rpm -e --nodeps mysql80-community-r ...

  9. 怎么查看linux文件夹下有多少个文件(mac同样)

    查看目录下有多少个文件及文件夹,在终端输入 ls | wc -w 查看目录下有多少个文件,在终端输入 ls | wc -c 查看文件夹下有多少个文件,多少个子目录,在终端输入 ls -l |wc -l ...

  10. nes 红白机模拟器 第8篇 USB 手柄支持

    买了一个支持 USB OTG, 蓝牙 连接的 安卓手柄. 接到 ubunto 上 dmesg 可以看到识别出来的信息,内核已经支持了. usb - using uhci_hcd usb - usb - ...