一、前言

在MySQL中进行SQL优化的时候,经常会在一些情况下,对MySQL能否利用索引有一些迷惑。

譬如:

  1. MySQL 在遇到范围查询条件的时候就停止匹配了,那么到底是哪些范围条件?

  2. MySQL 在LIKE进行模糊匹配的时候又是如何利用索引的呢?

  3. MySQL 到底在怎么样的情况下能够利用索引进行排序?

今天,我将会用一个模型,把这些问题都一一解答,让你对MySQL索引的使用不再畏惧。

二、知识补充

key_len

EXPLAIN执行计划中有一列 key_len 用于表示本次查询中,所选择的索引长度有多少字节,通常我们可借此判断联合索引有多少列被选择了。

在这里 key_len 大小的计算规则是:

  • 一般地,key_len 等于索引列类型字节长度,例如int类型为4 bytes,bigint为8 bytes;

  • 如果是字符串类型,还需要同时考虑字符集因素,例如:CHAR(30) UTF8则key_len至少是90 bytes;

  • 若该列类型定义时允许NULL,其key_len还需要再加 1 bytes;

  • 若该列类型为变长类型,例如 VARCHAR(TEXT\BLOB不允许整列创建索引,如果创建部分索引也被视为动态列类型),其key_len还需要再加 2 bytes;

三、哪些条件能用到索引

首先非常感谢登博,给了我一个很好的启发,我通过他的文章_,然后结合自己的理解,制作出了这幅图:

乍一看,是不是很晕,不急,我们慢慢来看

图中一共分了三个部分:

  1. Index Key :MySQL是用来确定扫描的数据范围,实际就是可以利用到的MySQL索引部分,体现在Key Length。

  2. Index Filter:MySQL用来确定哪些数据是可以用索引去过滤,在启用ICP后,可以用上索引的部分。

  3. Table Filter:MySQL无法用索引过滤,回表取回行数据后,到server层进行数据过滤。

下面我们细细展开。

Index Key

Index Key是用来确定MySQL的一个扫描范围,分为上边界和下边界。

MySQL利用=、>=、> 来确定下边界(first key),利用最左原则,首先判断第一个索引键值在where条件中是否存在,如果存在,则判断比较符号,如果为(=,>=)中的一种,加入下边界的界定,然后继续判断下一个索引键,如果存在且是(>),则将该键值加入到下边界的界定,停止匹配下一个索引键;如果不存在,直接停止下边界匹配。

exp:
idx_c1_c2_c3(c1,c2,c3)
where c1>=1 and c2>2 and c3=1
-->  first key (c1,c2)
--> c1为 '>=' ,加入下边界界定,继续匹配下一个
-->c2 为 '>',加入下边界界定,停止匹配

上边界(last key)和下边界(first key)类似,首先判断是否是否是(=,<=)中的一种,如果是,加入界定,继续下一个索引键值匹配,如果是(<),加入界定,停止匹配

exp:
idx_c1_c2_c3(c1,c2,c3)
where c1<=1 and c2=2 and c3<3
--> last key (c1,c2,c3)
--> c1为 '<=',加入上边界界定,继续匹配下一个
--> c2为 '='加入上边界界定,继续匹配下一个
--> c3 为 '<',加入上边界界定,停止匹配

注:这里简单的记忆是,如果比较符号中包含'='号,'>='也是包含'=',那么该索引键是可以被利用的,可以继续匹配后面的索引键值;如果不存在'=',也就是'>','<',这两个,后面的索引键值就无法匹配了。同时,上下边界是不可以混用的,哪个边界能利用索引的的键值多,就是最终能够利用索引键值的个数。

Index Filter

字面理解就是可以用索引去过滤。也就是字段在索引键值中,但是无法用去确定Index Key的部分。

exp:
idex_c1_c2_c3
where c1>=1 and c2<=2 and c3 =1
index key --> c1
index filter--> c2 c3

这里为什么index key 只是c1呢?因为c2 是用来确定上边界的,但是上边界的c1没有出现(<=,=),而下边界中,c1是>=,c2没有出现,因此index key 只有c1字段。c2,c3 都出现在索引中,被当做index filter.

Table Filter

无法利用索引完成过滤,就只能用table filter。此时引擎层会将行数据返回到server层,然后server层进行table filter。

四、Between 和Like 的处理

那么如果查询中存在between 和like,MySQL是如何进行处理的呢?

Between

where c1 between 'a' and 'b' 等价于 where c1>='a' and c1 <='b',所以进行相应的替换,然后带入上层模型,确定上下边界即可

Like

首先需要确认的是%不能是最在最左侧,where c1 like '%a' 这样的查询是无法利用索引的,因为索引的匹配需要符合最左前缀原则

where c1 like 'a%'  其实等价于 where c1>='a' and c1<'b' 大家可以仔细思考下。

五、索引的排序

在数据库中,如果无法利用索引完成排序,随着过滤数据的数据量的上升,排序的成本会越来越大,即使是采用了limit,但是数据库是会选择将结果集进行全部排序,再取排序后的limit 记录,而且MySQL 针对可以用索引完成排序的limit 有优化,更能减少成本。

Make sure it uses index It is very important to have ORDER BY with LIMIT executed without scanning and sorting full result set, so it is important for it to use index – in this case index range scan will be started and query execution stopped as soon as soon as required amount of rows generated.

CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` int(11) NOT NULL DEFAULT '0',
  `c2` int(11) NOT NULL DEFAULT '0',
  `c3` int(11) NOT NULL DEFAULT '0',
  `c4` int(11) NOT NULL DEFAULT '0',
  `c5` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idx_c1_c2_c3` (`c1`,`c2`,`c3`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

 select * from t1;
+----+----+----+----+----+----+
| id | c1 | c2 | c3 | c4 | c5 |
+----+----+----+----+----+----+
|  1 |  3 |  3 |  2 |  0 |  0 |
|  2 |  2 |  4 |  5 |  0 |  0 |
|  3 |  3 |  2 |  4 |  0 |  0 |
|  4 |  1 |  3 |  2 |  0 |  0 |
|  5 |  1 |  3 |  3 |  0 |  0 |
|  6 |  2 |  3 |  5 |  0 |  0 |
|  7 |  3 |  2 |  6 |  0 |  0 |
+----+----+----+----+----+----+
7 rows in set (0.00 sec)

 select c1,c2,c3 from t1;
+----+----+----+
| c1 | c2 | c3 |
+----+----+----+
|  1 |  3 |  2 |
|  1 |  3 |  3 |
|  2 |  3 |  5 |
|  2 |  4 |  5 |
|  3 |  2 |  4 |
|  3 |  2 |  6 |
|  3 |  3 |  2 |
+----+----+----+
7 rows in set (0.00 sec)

存在一张表,c1,c2,c3上面有索引,select c1,c2,c3 from t1; 查询走的是索引全扫描,因此呈现的数据相当于在没有索引的情况下select c1,c2,c3 from t1 order by c1,c2,c3; 的结果。

因此,索引的有序性规则是怎么样的呢?

c1=3 —> c2 有序,c3 无序
c1=3,c2=2 — > c3 有序
c1 in(1,2) —> c2 无序 ,c3 无序

有个小规律,idx_c1_c2_c3,那么如何确定某个字段是有序的呢?c1 在索引的最前面,肯定是有序的,c2在第二个位置,只有在c1 唯一确定一个值的时候,c2才是有序的,如果c1有多个值,那么c2 将不一定有序,同理,c3也是类似

六、小结

针对MySQL索引,我这边只是提到了在单表查询情况下的模型,通过这篇文章,想必大家应该了解到MySQL大部分情况下是如何利用索引的。

欢迎关注公众号:程序员追风,领取Java知识点学习思维导图总结+一线大厂Java面试题总结+一份300页pdf文档的Java核心知识点总结!

MySQL索引的使用是怎么样的?5个点轻松掌握!的更多相关文章

  1. 深入MySQL索引

    MySQL索引作为数据库优化的常用手段之一在项目优化中经常会被用到, 但是如何建立高效索引,有效的使用索引以及索引优化的背后到底是什么原理?这次我们深入数据库索引,从索引的数据结构开始说起. 索引原理 ...

  2. MySQL 索引

    MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是 ...

  3. MYSQL索引结构原理、性能分析与优化

    [转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...

  4. MySQL索引原理及慢查询优化

    原文:http://tech.meituan.com/mysql-index.html 一个慢查询引发的思考 select count(*) from task where status=2 and ...

  5. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  6. [转]MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  7. MySQL索引类型总结和使用技巧以及注意事项

    索引是快速搜索的关键.MySQL索引的建立对于MySQL的高效运行是很重要的.下面介绍几种常见的MySQL索引类型 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable ...

  8. MySQL索引背后的数据结构及算法原理【转】

    本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...

  9. mysql索引总结----mysql 索引类型以及创建

    文章归属:http://feiyan.info/16.html,我想自己去写了,但是发现此君总结的非常详细.直接搬过来了 关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基 ...

  10. Mysql 索引实现原理. 聚集索引, 非聚集索引

    Mysql索引实现: B-tree,B是balance,一般用于数据库的索引.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.而B+tree是B-tree的一个变种,My ...

随机推荐

  1. 详解CorelDRAW中刻刀工具的具体运用

    通过CorelDRAW,我们可以将一个对象拆分为两个对象,使用刻刀工具就可以将对象一分为二,保存为一个由两个或者多个子路径组成的对象,可以指定是否要自动闭合路径,或者是否一直将它们打开. CDR刻刀工 ...

  2. 堆的数据结构java

    public class MaxHeap { private int[] data; private int count; private int capacity; public MaxHeap(i ...

  3. 使用ES替代whoosh全文检索

    目录 1.docker安装ES 1.拉取docker镜像 2.使用docker安装ES 3.在页面中测试 2.使用ES替代whoosh全文检索 2.1 在Django中修改搜索引擎为ES 2.2 命令 ...

  4. python—数据类型和变量

    在python中,能够直接处理的数据类型和变量有整数.浮点数.字符串.布尔值.空值.变量. 一.整数 1.python可处理任意大小的整数,包括负整数,在程序中的表示方法与在数学中的方法一样.例如:0 ...

  5. java中的强引用(Strong reference),软引用(SoftReference),弱引用(WeakReference),虚引用(PhantomReference)

    之前在看深入理解Java虚拟机一书中第一次接触相关名词,但是并不理解,只知道Object obj = new Object()类似这种操作的时候,obj就是强引用.强引用不会被gc回收直到gc roo ...

  6. DjangoForm表单组件

    Form组件的介绍: 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验 ...

  7. MVTMVC 区别

    1,MVC的意思是 M:model V:views C:controller model是  主要是封装对数据库层的访问,对数据库中的数据进行增删改查操作 views 是 用于封装结果, 生程页面展示 ...

  8. 第9.13节 Python文件操作总结

    本章老猿重点介绍了Python io模块的文件操作相关功能,包括文件打开.读.写.文件定位.文件关闭,并介绍了二进制文件和文本文件处理的差异,以及相关文件编码的一些知识,最后简单提及了Python中与 ...

  9. PyQt(Python+Qt)学习随笔:Model/View架构中的Model模型概念

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Model/View架构中的Model模型Model与数据源通信,为体系结构中的其他组件提供数据接口 ...

  10. PyQt(Python+Qt)学习随笔:Qt Designer中怎么给toolBar添加按钮

    在Designer中创建了一个MainWindow窗体,当想在其中的toolBar中添加toolButton时发现怎么也放不上去,最终才发现toolBar中的按钮只能通过直接拖拽Action编辑器中的 ...