看前提问: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. JAVA:初识Java · Xer97

    1. 什么是Java Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. Java语言作为静 ...

  2. 新财报再次巨亏 HTC还能活到2017吗?

    HTC还能活到2017吗?" title="新财报再次巨亏 HTC还能活到2017吗?"> 当下智能手机行业虽然竞争惨烈,但也称得上是精彩纷呈:性能.外形不断进化, ...

  3. nGrinder 介绍与安装

    nGrinder是基于Grinder开源项目,但由NHN公司的nGrinder开发团队进行了重新设计和完善(所以叫做nGrinder). 它是由一个controller和连接它的多个agent组成,用 ...

  4. 重大改革!Python将被加入高考科目!

    未来大学生将分为两种:一种是编程好的人,另一种是编程超好的人. Python 将被纳入高考科目 近期,浙江省信息技术课程改革方案出台,Python 确定进入浙江省信息技术高考,从2018年起浙江省信息 ...

  5. ubuntu 代理设置

    在学习工作中使用vagrant作为开发环境已经有很长一段时间了,使用ubuntu 作为开发系统 在使用中发现,即使修改了apt的source.list源文件,在面对一些开发中需要的软件工具的时候,不可 ...

  6. 分布式系统一致性问题与Raft算法(上)

    最近在做MIT6.824的几个实验,真心觉得每一个做分布式相关开发的程序员都应该去刷一遍(裂墙推荐),肯定能够提高自己的技术认知水平,同时也非常感谢MIT能够把这么好的资源分享出来. 其中第二个实验, ...

  7. C++扬帆远航——6(三色球)

    /* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:sanseqiu.cpp * 作者:常轩 * 完成日期:2016 ...

  8. P1678 烦恼的高考志愿

    P1678题库链接:https://www.luogu.org/problem/P1678 难度:普及- 算法标签:模拟,贪心,排序,二分查找 1.朴素模拟 O(m*n) 得分30 先将m个学校的录取 ...

  9. 第六周学习笔记,vc各类控件的输入输出

    6w学习笔记 vc控件的输入输出 单选按钮 当单击 RadioButton 控件时,其 Checked 属性设置为 true,并且调用 Click 事件处理程序.当 Checked 属性的值更改时,将 ...

  10. prometheus服务发现机制

    一. Prometheus与服务发现 1.1 目前支持的服务发现方式 二. 案例 2.1 基于文件的服务发现 2.2 基于Consul的服务发现 三.本地测试 3.1 基于文件的服务发现 1.测试环境 ...