白日梦的MySQL专题(第38篇文章)8分钟回顾MySQL的索引
公众号首发-推荐阅读原文-格式更好看
一、导读
在MySQL中,不仅为主键创建的聚簇索引选用的数据结构是B+Tree,像辅助索引,二级索引、覆盖索引、联合索引等等其实都是B+Tree。
二、聚簇索引
MySQL默认为 int 类型的主键创建一个聚簇索引。这棵B+Tree是如何设计、如何长高可以参考上一篇文章。
https://mp.weixin.qq.com/s/TwcNEzEWg0PpN0Ra_kiTag
这颗B+Tree之所以叫做聚簇索引是因为它的叶子节点中存储的是完整的数据行,也就是说你拿着id从这棵树的根索引上检索,一直到叶子节点并且定位到特定的数据页后,你是可以去除完整的数据行来的!(所有列都有)
三、二级索引
二级索引也被大家称为辅助索引,其实每个索引都是对应一棵独立的B+Tree,而且他们都有这个特性:后面的数据页中的索引值均比它前面的数据页中的索引值大,并且都会通过页分裂的机制保证这个特性一致成立。
不同的是不同索引的叶子节点中存储的数据是不一样的!对于二级索引来说它的叶子节点中存储的不再是完整的数据行,而是id值。
比如表里面有 id、age、name、addr四列,且name列是二级索引。然后你的SQL是这样的
select * from table
where name = 'tom';
那就会先扫描name列这颗B+Tree,找到name=‘tom’所在的叶子节点,叶子节点中存储的只有name = ‘tom’的这行数据在表中的id值。于是再拿着这个id值去聚簇索引中重新查询,这个动作我们称为:“回表”
你可以像下面这样创建二级索引
CREATE INDEX [index name] ON [table name]([column name]);
或者
ALTER TABLE [table name] ADD INDEX [index name]([column name]);
四、联合索引
4.1、什么是联合索引
联合索引也叫复合索引,说白了就是多个字段一起组合成一个索引。
像下面这样使用 id + title 组合在一起构成一个联合索引
CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`,`title`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8
# 或者通过这种方式添加联合索引
alter table text add INDEX `t3_index_title_content` (`title`,`content`);
- 如果我们像上图那样创建了索引,我们只要保证 id+title 两者结合起来全局唯一就ok
- 建立联合索引同样是需要进行排序的,排序的规则就是按照联合索引所有列组成的字符串的之间的先后顺序进行排序,,如a比b优先。
4.2、左前缀原则
使用联合索引进行查询时一定要遵循左前缀原则。
什么是左前缀原则呢?
就是说想让索引生效的话,一定要添加上第一个索引,只使用第二个索引进行查询的话会导致索引失效。
比如上面创建的联合索引,假如我们的查询条件是 where id = '1' 或者 where id = '1' and title = '唐诗宋词' 索引都会不失效。
但是如果我们不使用第一个索引id,像这样 where title = '唐诗' ,结果就是导致索引失效。
问:如果我不遵循做前缀原则,一定不能使用聚簇索引吗?
回答:不是的!可以看下面的例子:
# t3表中有3个索引,如下:
# id:聚簇索引
# x1:唯一的二级索引
# x1_x3_x2:联合索引
explain select * from t3 where x2 = 'fdc1a9f7d94ece2b68b7d3e3be1b0f3b';
可以看到,x2列没有单独的索引。但是sql的执行计划选择去联合索引树中扫全表,也不会去聚簇索引中全表扫描。

这里只需要大概看懂这个执行计划就ok,下一讲详细讲!
4.3、联合索引的分组&排序
还是使用这个例子:
CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`,`title`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8
demo1: 当我们像下面这样写sql时,就会先按照id进行排序。当id相同时再按照title进行排序。
select * form text order by id, title;
demo2: 当我们像下面这样写sql时,就会先将id相同的划分为一组,再将title相同的划分为一组。
select id,title form text group by id, title;
demo3: ASC和DESC混用, 其实大家都知道底层使用B+树,本身就是有序的。要是不加限制的话,默认就是ASC。反而是混着使用就使得索引失效。
select * form text order by id ASC, title DESC;
另外补充一点:如果你的group by xxx列,这一列没有索引时,mysql会 Using temporary 也就是中间表来实现你的分组操作,效率是很低的! 而如果有索引的话,直接走索引就可以实现 group by。
五、覆盖索引
覆盖索引其实和二级索引没啥区别,只不过是查询方式不同而让它省去了回表的操作而已。
还是这个例子:
比如表结构是这样的
CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`title`,`content`)
) ENGINE=InnoDB AUTO_INCREMENT=3691 DEFAULT CHARSET=utf8
然后你的SQL是这样的
select content from table
where title = 'all in';
你会发现,其实select中期望得到的内容已经全部存在于辅助索引中了,所以不需要再使用id进行回表操作也能得到正确的返回值。
这其实在一定程度上也说明了别总是动不动就select *,能走覆盖索引尽量使用覆盖索引。哪怕是不得不进行一次回表操作也尽量使用limit、where条件限制一下!
六、倒排索引
InnoDB中是存在倒排索引和全文检索的概念的!
MySQL的inverted index同B+Tree索引一样。另外会使用一张辅助表来存储单词和document之间的映射关系。
比如它的倒排索引表长下面这样:
| Number | Text | Documents |
|---|---|---|
| 1 | old | 1,4 |
| 2 | hot | 2,5 |
解读上表:old这个单词在document1和doc4中出现过。 单词hot在doc2、doc5中出现过
full inverted index关联数据长下面这样
| Number | Text | Documents |
|---|---|---|
| 1 | code | (1,4), (2,5) |
| 2 | review | (3,5),(5,8) |
解读上表:单词code在doc1的第4个单词的位置上出现了。同理单词review也类似。
但是一般我们一说到全文检索或者是倒排索引往往都会直观的想到:Elasticsearch 这款NoSQL
因为InnoDB存储引擎的全文检索是存在限制的:
- 每张表只能有一个全文检索的索引
- 由多列组合而成的全文检索的索引列必须使用相同的字符集
- 不支持没有单词界定符的语言,如:中文、日语、韩语
- MySQL的修仙之路,图文谈谈如何学MySQL、如何进阶!(已发布)
- 面前突击!33道数据库高频面试题,你值得拥有!(已发布)
- 大家常说的基数是什么?(已发布)
- 讲讲什么是慢查!如何监控?如何排查?(已发布)
- 对NotNull字段插入Null值有啥现象?(已发布)
- 能谈谈 date、datetime、time、timestamp、year的区别吗?(已发布)
- 了解数据库的查询缓存和BufferPool吗?谈谈看!(已发布)
- 你知道数据库缓冲池中的LRU-List吗?(已发布)
- 谈谈数据库缓冲池中的Free-List?(已发布)
- 谈谈数据库缓冲池中的Flush-List?(已发布)
- 了解脏页刷回磁盘的时机吗?(已发布)
- 用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!(已发布)
- 听说过表空间没?什么是表空间?什么是数据表?(已发布)
- 谈谈MySQL的:数据区、数据段、数据页、数据页究竟长什么样?了解数据页分裂吗?谈谈看!(已发布)
- 谈谈MySQL的行记录是什么?长啥样?(已发布)
- 了解MySQL的行溢出机制吗?(已发布)
- 说说fsync这个系统调用吧! (已发布)
- 简述undo log、truncate、以及undo log如何帮你回滚事物! (已发布)
- 我劝!这位年轻人不讲MVCC,耗子尾汁! (已发布)
- MySQL的崩溃恢复到底是怎么回事? (已发布)
- MySQL的binlog有啥用?谁写的?在哪里?怎么配置 (已发布)
- MySQL的bin log的写入机制 (已发布)
- 删库后!除了跑路还能干什么?(已发布)
- 自导自演的面试现场,趣学数据库的10种文件(已发布)
- 大型面试现场:一条update sql执行都经历什么?(已发布)
- 大型翻车现场:如何实现记录存在的话就更新,如果记录不存在的话就插入。(已发布)
- 视频+图文串讲:MySQL 行锁、间隙锁、Next-Key-Lock、以及实现记录存在的话就更新,如果记录不存在的话就插入如何保证并发安全(已发布)
- 自导自演的面试现场:说说char 和 varchar的区别你了解多少?。(已发布)
- 自导自演的面试现场之--你竟然不了解MySQL的组提交?。(已发布)
- 全网最清楚的:MySQL的insert buffer和change buffer 串讲(已发布)
- Double Write并不难理解
- 简述MySQL的三大范式
- 盘点各种登陆数据库的方式
- 面试现场:join联表的注意点、有哪些联表查询方式、真题...
35.心里有点树
36.心里有点B树
37.聚簇索引到底是怎么回事?是如何长高的?
38.8分钟回顾MySQL的索引
白日梦的MySQL专题(第38篇文章)8分钟回顾MySQL的索引的更多相关文章
- 这篇文章告诉你MYSQLB+树具体索引数据组织明细内容
面试题:InnoDB中一棵B+树能存多少行数据? 一.InnoDB 一棵 B+ 树可以存放多少行数据? InnoDB 一棵 B+ 树可以存放多少行数据? 这个问题的简单回答是:约 2 千万. 为什 ...
- 白日梦的MySQL专题(第33篇):各种登陆MySQL的骚操作
阅读原文 系列文章公众号首发,点击阅读原文 前置知识 我们想登陆到mysql中前提是肯定需要一个用户名和密码:比如 mysql -uroot -proot 在mysql中用户的信息会存放在 mysql ...
- Golang分布式爬虫:抓取煎蛋文章|Redis/Mysql|56,961 篇文章
--- layout: post title: "Golang分布式爬虫:抓取煎蛋文章" date: 2017-04-15 author: hunterhug categories ...
- mysql中的中文乱码解决方案, 全部是 这篇文章的内容: https://www.52jbj.com/jbdq/18755.html
我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,总得知道个一二吧,不然以后如何优雅的吹牛B. 如果你也遇到了这个问题,咱 ...
- 安装篇五:安装MySQL(5.6.38版本)
#1.MySQL安装 #1.准备环境 # No1:关闭:(iptables)selinux # No2:下载好安装包(这里使用 mysql-5.6.38.tar.gz 包安装) # No3:安装依赖包 ...
- 如果有人问你 MySql 怎么存取 Emoji,把这篇文章扔给他
01.前言 Emoji 在我们生活中真的是越来越常见了,几乎每次发消息的时候不带个 Emoji,总觉得少了点什么,似乎干巴巴的文字已经无法承载我们丰富的感情了.对于我们开发者来说,如何将 Emoji ...
- 如何优雅的备份MySQL数据?看这篇文章就够了
大家好,我是一灯,今天一块学习一下如何优雅安全的备份MySQL数据? 1. 为什么要备份数据 先说一下为什么需要备份MySQL数据? 一句话总结就是:为了保证数据的安全性. 如果我们把数据只存储在一个 ...
- MySQL Performance-Schema(二) 理论篇
MySQL Performance-Schema中总共包含52个表,主要分为几类:Setup表,Instance表,Wait Event表,Stage Event表Statement Event表,C ...
- Python自动化 【第十二篇】:Python进阶-MySQL和ORM
本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 外键 增删改查表 权限 事务 索引 python 操作mysql ORM sql ...
随机推荐
- SpringBoot配置切换
切换需求 有时候在本地测试是使用8080端口,可是上线使用的又是80端口. 此时就可以通过多配置文件实现多配置支持与灵活切换. 多配置文件 3个配置文件: 核心配置文件:application.pro ...
- php基础-php中使用变量
- keep-alive与生命周期函数
理解keep-alive keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 router-view也是一个组件,如果直接被keep-alive包在里面,所有路径匹 ...
- docker运行mysql数据库
1.搜索镜像源是否有mysql镜像 执行语句: sudo docker search mysql 2.拉取需要版本的mysql,执行语句: docker pull mysql:5.7 3.查看安装 ...
- [Java] Spring 原理
IOC(Inverse of Control)控制反转 依赖对象的获得被反转了,由自己创建变为从IOC容器获取 优点 代码更简介,不需要new对象 面向接口编程,使用者与具体类解耦,易扩展 方便进行A ...
- 佳能m62套机5500 佳能EOS M50 M6 MARK2 II二代 最低到过5800
佳能m62套机5500 佳能EOS M50 M6 MARK2 II二代
- Win10屏幕亮度不能调节,调节无效怎么办?
Win10屏幕亮度不能调节,调节无效怎么办? 听语音 浏览:1027 | 更新:2019-11-22 11:43 1 2 3 4 5 6 7 分步阅读 一些用户在使用win10系统之后,出现了电脑屏幕 ...
- 如果你想设置无人自动升级,我们推荐你将这个值修改为security,它会告诉 yum 仅仅升级修复安全问题的软件包。
定期升级你的 CentOS 系统,是所有系统安全中最重要的措施之一.如果你不使用最新的安全补丁升级你的操作系统软件包,你将会让你的机器很容易被攻击. 如果你管理者多个 CentOS 机器,手动升级系统 ...
- shell基础之exit,break,continue
exit代码: 1 #!/bin/bash 2 echo "Is it morning? Please answer yes or no." 3 read YES_OR_NO 4 ...
- 高通 QC协议 谷歌 PD协议
高通 QC协议 谷歌 PD协议 上述协议是两款充电协议 现在已经应用于智能设备的充电中了 https://jingyan.baidu.com/article/7908e85cb04b1baf48 ...