MySQL 笔记整理(5) --深入浅出索引(下)
笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》
5) --深入浅出索引(下)
这次的笔记从一个简单的查询开始:
建表语句是这样的
mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0,
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB; insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');
如果要执行 select * from T where k between 3 and 5这条语句,需要执行几次搜索操作呢,会扫描多少行呢?由上面的建表及初始化语句我们很容易可以看出,表T上有ID字段的主键索引,也有K字段上的非主键索引。数据中满足条件K在3和5之间的记录有两条,分别是 (300,3,'cc'),(500,5,'ee')。我们在K字段上创建了索引,所以在执行这条语句时,MySQL就会使用这个索引。如果你看了我上篇笔记的话应该知道,K上的索引是非主键索引,而非主键索引存储的其实是主键的值。所以这条语句的执行流程大致是下面这个样子的。
- 在K索引树上找到K=3的记录,取得ID=300.
- 再到ID索引树查到ID=300对应的记录。(第一次回表)
- 在K索引树上找到K=5的记录,取得ID=500.
- 再到ID索引树查到ID=500对应的记录。(第二次回表)
- 在K索引树取下一个值K=6,不符合条件,查询结束。
所以上面这条语句查询了3条记录K=3,5,6.回表了两次。
我们注意到一个细节,select * from T where k between 3 and 5这条语句查询的结果是*,也就是所有的字段的内容都会返回。而如果只使用K上的索引,则只能查询到ID的值与K的值,并不能返回符合要求的所有字段的值。那么如果K上的索引查询的结果可以满足要求,是不是就不需要回表了呢?答案是肯定的。 如语句 SELECT ID from T where k between 3 and 5; ID的值已经在K索引树上了,不需要回表就能返回结果。即索引“K”已经覆盖了我们的查询需求,我们称为覆盖索引。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
上面的例子中还有一个小细节需要注意一下:在引擎内部使用索引K其实读了三个记录,但对于MySQL的Server层来说,它就是找引擎拿到了两条记录。
最左前缀原则:
InnoDB使用B+树这种索引模型,由于B+树的索引结构,可以利用索引的"最左前缀"来定位记录。如你在‘name’字段上建立了索引,当你的语句是 where name like ‘张%’时是可以使用索引的。MySQL会利用这个索引向后遍历,直到不满足条件为止。不止是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左N个字符。索引建立联合索引的时候,如何安排索引内字段的顺序就很重要了。 有一个原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序就往往是应该优先采用的。
如果既有联合查询,又有基于a,b各自的查询呢?如果你建立的联合索引是(a,b),那么在这种情况下,只使用b来查询是没办法使用索引的。这种时候我们需要优先考虑的就是空间了。如(name,age),name字段一般来说会比age字段占用更多的空间,那么我们建立一个(name,age)的索引再加上一个(age)的索引就好了。
索引下推:
还是上面的(name,age)索引为例,如果你查询的条件是 姓张,且年龄小于30岁的所有男生,那么你的查询语句应该这么写。 select * from T where name like '张%' and age = 10 and ismale = true; 由于索引前缀的规则,只能使用‘张’来找到满足条件的记录,然后再判断查询的其他条件是否满足。在MySQL5.6之前,每条满足条件 like '张%'的记录都会回表进行判断。MySQL5.6之后引入了索引下推(index condition pushdown),可以在索引遍历的过程中对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表的次数。举个例子来说明 对于记录 A(张一,40,男),B(张二,25,男),C(张三,26,女)。没有索引下推时,A,B,C都需要进行回表判断。有索引下推以后,A记录中的age值为40,age字段在查询条件中,也在索引(name,age)中,触发了索引下推,不进行回表。B,C仍需要回表。
上篇问题答案:
对于普通索引k,重建时可以这么写:
alter table T drop index k; alter table T add Index(k);
对于主键索引,可以这么写:
alter table T drop primary key; alter table T add primary key(id);
对于上面的重建索引的作法,说出你的理解。如果有不合时的,为什么?更好的作法是什么?
首先来回答一下为什么要重建索引? 索引可能因为记录的删除,或者页分裂等原因,导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面的利用率最高,也就是索引更紧凑,更省空间。
重建索引K的做法是合理的。但重建主键过程不合理。不论是删除主键还是创建主键,都会将整个表进行重建,所以连续执行这两条语句,相当于第一个语句白做了。这两条语句可以使用 alter table T engine =InnoDB来代替。
问题:
表结构如下所示:
CREATE TABLE `geek` (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`,`b`),
KEY `c` (`c`),
KEY `ca` (`c`,`a`),
KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;
由于历史原因, a和b需要做联合主键。那么既然主键包括了a,b这两个字段,又单独在c上创建了一个索引,索引就已经包含了三个字段了,为什么还要创建ca,cb索引呢?有人给出的理由是业务里有这样两个查询:
select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;
这个理由对吗?为了这两个查询,这两个索引是否都必须呢?为什么呢?
MySQL 笔记整理(5) --深入浅出索引(下)的更多相关文章
- 最全mysql笔记整理
mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...
- MySQL 笔记整理(4) --深入浅出索引(上)
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 4) --深入浅出索引(上) 一句话简单来说,索引的出现其实就是为了提高数据查询的效率,就像书的目录一样. 索引的常见模型 哈希表: ...
- MySQL 笔记整理(10) --MySQL为什么有时会选错索引?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 10) --MySQL为什么有时会选错索引? MySQL中的一张表上可以 ...
- MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...
- MySQL 笔记整理(11) --怎么给字符串字段加索引?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 11) --怎么给字符串字段加索引? 日常工作中的登录系统,你很可能会使 ...
- MySQL 笔记整理(9) --普通索引和唯一索引,应该怎么选择?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 9) --普通索引和唯一索引,应该怎么选择? 假如你在维护一个市民系统, ...
- MySQL 笔记整理(16) --“order by”是怎么工作的?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 16) --“order by”是怎么工作的? 在林老师的课程中,第15 ...
- MySQL 笔记整理(19) --为什么我只查一行的语句,也执行这么慢?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 19) --为什么我只查一行的语句,也执行这么慢? 需要说明一下,如果M ...
- MySQL 笔记整理(14) --count(*)这么慢,我该怎么办?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 14) --count(*)这么慢,我该怎么办? 有时你会发现,随着系统 ...
随机推荐
- 用gulp-imageisux智图api压缩图片
➣ 智图平台是什么? 智图是腾讯ISUX前端团队开发的一个专门用于图片压缩和图片格式转换的平台,其功能包括针对png,jpeg,gif等各类格式图片的压缩,以及为上传图片自动选择最优的图片格式.同时, ...
- swust oj 987
输出用先序遍历创建的二叉树是否为完全二叉树的判定结果 1000(ms) 10000(kb) 2553 / 5268 利用先序递归遍历算法创建二叉树并判断该二叉树是否为完全二叉树.完全二叉树只能是同深度 ...
- CSS引用方式及样式层叠机制
CSS引用方式有3种,三种分别为:外部引入.内部引入.行内样式,下面一 一进行介绍. 1.外部引入:CSS代码在一个独立的文件中,HTML通过Link标签引入到页面. 代码格式:<link re ...
- SSIS - 3.变量
跟其他变成语言一样,SSIS包中的变量是用来存储临时值的,变量使得整个SSIS包使用起来更加灵活.比如,我们可以遍历一个文件夹来获取文件夹下的所有文件的名称并把名称存储到一个变量中以便进一步处理.在S ...
- 企业IT管理员IE11升级指南【13】—— 如何把IEMP迁移到GPP
企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...
- 【子集或者DFS】部分和问题
题目: 给定整数序列a1,a2,...,an,判断是否可以从中选出若干数,使它们的和恰好为k.1≤n≤20 -108≤ai≤108 -108≤k≤108 输入: n=4 a={1,2,4,7} ...
- [Swift]LeetCode700. 二叉搜索树中的搜索 | Search in a Binary Search Tree
Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST ...
- Vue入门手册整理
目录 第一章.环境搭建 第二章.目录结构 第三章.Vue调试 第四章.定义页面 附录资料 第一章.环境搭建 1.1.准备: npm: 6.9.0 (npm > 3.0) node: v10.15 ...
- Android开发:Android虚拟机启动错误Can't find 'Linux version ' string in kernel image file
Android启动出错,虚拟机报错信息如下: Starting emulator for AVD 'test' emulator: ERROR: Can't find 'Linux version ' ...
- Python 工厂函数和内建函数
工厂函数 工厂函数都是类对象, 即当你调用他们时, 创建的其实是一个类实例 例如: str(), list(), tuple()... 内建函数 内建函数通常是python自定义的一些函数, 这些函数 ...