【Mysql】InnoDB 中的聚簇索引、二级索引、联合索引
接上一篇内容。
一、聚簇索引
其实之前内容中介绍的 B+ 树就是聚簇索引。
这种索引不需要我们显示地使用 INDEX 语句去创建,InnoDB 引擎会自动创建。另外,在 InnoDB 引擎中,聚簇索引就是数据的存储方式。
它有 2 个特点:
特点 1
使用记录主键值的大小进行记录和页的排序。
其中又包含了下面 3 个点:
页(包括叶节点和内节点)内的记录按照主键的大小顺序排成一个单向链表。页内记录划分为若干组,每个组中主键值最大的记录在页内的偏移量被当做槽依次存放在页目录中。我们可以通过二分法快速定位主键值等于某个值的记录。
各存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表。
各存放目录项记录的页分为不同层级。在同一层级中的页,也是根据页中目录项记录的主键大小顺序排成一个双向链表。
特点 2
B+树的叶子节点存储的是完整的用户记录。
这里完整的用户记录就是指,这个记录中存储了所有的列的值(包括隐藏列)。
二、二级索引
聚簇索引只能在我们搜索主键值时才能发挥作用,因为 B+ 树中的数据都是按照主键进行排序。
如果现在我用“别的列”作为搜索条件,怎么办?
答案:再建一个 B+ 树,用这个“别的列”(非主键列)的值大小作为排序规则。
比如之前的内容都是以 c1 列为主键,现在用 c2 列再来创建一个 B+ 树:

看起来跟之前的聚簇索引没啥区别啊?实际上还是存在不同的:
- 使用记录 c2 列的大小进行记录和页的排序。细分的 3 点与上面聚簇索引介绍的一样,只不过上面是主键,这里是用的 c2 列(非主键)。
- B+ 树的叶子节点存储的不是完整的用户记录,只有
c2 列 + 主键这2个列的值。 - 目录项记录中不再是
主键 + 页号,变成了c2 列 + 页号。
另外需要注意的是,因为 c2 列不是主键,所以没有唯一性约束,可能存在多条满足搜索条件的数据。
现在根据条件 c2 = 4 来查找数据记录,过程如下:
- 确定第一条符合 c2 = 4 的目录项所在页,也就是页 42。
- 到页 42 中,进一步确定第一条符合条件的记录所在的用户记录页。因为 2 < 4 <= 4,所以可能存在 页 34 或 35 中。
- 先到页 34 中定位第一条满足 c2 = 4 的用户记录,如果有就不需要再到页 35 中继续定位了。
- 在页 34 中定位到第一条记录。因为这条用户记录不完整,所以拿到这条记录的主键,再到聚簇索引中找到完整的用户记录。
上面最后一步,通过携带主键信息到聚簇索引中重新定位完整的用户记录的过程也叫回表。
回表后,再回到这颗新的 B+ 树,找到刚才那个第一个符合条件的记录,并沿着记录的单向链表向后继续搜索其他也满足 c2 = 4 的记录,每找到一条就继续回表操作,重复这个过程。
这种以非主键列的大小为排序规则而建立 B+ 树需要执行回表操作才可以定位到完整的用户记录,这种 B+树就称为二级索引或者辅助索引。
为什么要回表?直接把完整用户记录都放叶子节点不就可以了?
没错,思路没问题。但是这样操作就相当于每建立一颗 B+ 树都把所有的用户记录复制一遍,太浪费存储空间。
三、联合索引
我们可以同时为多个列建立索引,比如 c2 列和 c3 列,以这 2 个列的大小为排序规则建立的 B+ 树索引就称为联合索引,也称为符合索引或多列索引。
这里的按照 c2 和 c3 列大小进行排序,需要注意两点:
- 先把各个记录和页按照 c2 列进行排序。
- 在记录的 c2 列都相同的情况下,再采用 c3 列进行排序。
现在,给c2 和 c3 建立联合索引,如图所示:

需要注意的是:
- 每条目录项记录都是由 c2、c3、页号这 3 部分组成。各记录先按照 c2 列的值进行排序,如果记录的 c2 列相同,则按照 c3 列进行排序。
- B+ 树叶子节点的用户记录由 c2、c3、和 主键c1 列组成。
本质上,联合索引也是一个二级索引,只不过它的索引列包括 c2、c3 这2个列。
本文参考书籍:
小孩子4919 《mysql是怎样运行的》
【Mysql】InnoDB 中的聚簇索引、二级索引、联合索引的更多相关文章
- MySql InnoDB中的锁研究
# MySql InnoDB中的锁研究 ## 1.InnoDB中有哪些锁### 1. 共享和排他(独占)锁(Shared and Exclusive Locks) InnoDB实现标准的行级锁定,其中 ...
- MySQL单列索引和组合索引(联合索引)的区别详解
发现index merge局限性,优化器会自动判断是否使用 index merge 优化技术,查询还是需要组合索引[推荐阅读:对mysql使用索引的误解] MySQL单列索引和组合索引(联合索引)的区 ...
- 关于mysql索引---联合索引
结论: mysql联合索引,联合索引以哪个字段开始很重要. 如果 联合索引字段为 1,2,3,4 那么如果查询条件为 6,7,8,1 这样也会走上面的联合索引 但是如果查询条件不是从1开始那么则 ...
- MySQL InnoDB中的事务隔离级别和锁的关系
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...
- MySQL -- Innodb中的change buffer
change buffer是一种特殊的数据结构,当要修改的辅助索引页不在buffer pool中时,用来cache对辅助索引页的修改.对辅助索引页的操作可能是insert.update和delete操 ...
- MySQL/InnoDB中,对于锁的认识
MySQL/InnoDB的加锁,一直是一个面试中常问的话题.例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?我在工作过程中,也会经常用到,乐观锁,排它锁,等.于是今天就对 ...
- (MYSQL)回表查询原理,利用联合索引实现索引覆盖
一.什么是回表查询? 这先要从InnoDB的索引实现说起,InnoDB有两大类索引: 聚集索引(clustered index) 普通索引(secondary index) InnoDB聚集索引和普通 ...
- MySQL/InnoDB中,乐观锁、悲观锁、共享锁、排它锁、行锁、表锁、死锁概念的理解
文章出处:https://www.souyunku.com/2018/07/30/mysql/?utm_source=tuicool&utm_medium=referral MySQL/Inn ...
- MySQL innodb中各种SQL语句加锁分析
概要 Locking read( SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),UPDATE以及DELETE语句通常会在他扫描的索引所 ...
随机推荐
- C# & JS 判断字符串是否为日期格式
在C#中,对格式的判断有一类专门函数,那就是TryParse.TryParse在各个不同的类型类(如int,string,DateTime)中,都是存在的.在TryParse中一般有两个参数,一个是待 ...
- springmvc——自定义类型转换器
一.什么是springmvc类型转换器? 在我们的ssm框架中,前端传递过来的参数都是字符串,在controller层接收参数的时候springmvc能够帮我们将大部分字符串类型的参数自动转换为我们指 ...
- 1738. 找出第 K 大的异或坐标值
2021-05-19 LeetCode每日一题 链接:https://leetcode-cn.com/problems/find-kth-largest-xor-coordinate-value/ 标 ...
- 【模板】Tarjian求LCA
概念 公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点 举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1. 算法 常用的求LCA的算法有:Ta ...
- ORACLE中的PL/SQL
一. 1.过程,函数,触发器是pl/sql编写. 2. 过程函数触发器是在Oracle中. 3.pl/sql是非常强大的数据库过 ...
- Linux常见信号介绍
1.信号 首先信号我们要和信号量区分开来,虽然两者都是操作系统进程通信的方式.可以简单的理解,信号是用来通知进程发生了什么需要做什么,信号量一般是用作进程同步(pv操作) 2.常见信号量 (以下数字标 ...
- Jetpack Compose和View的互操作性
Jetpack Compose Interoperability Compose风这么大, 对于已有项目使用新技术, 难免会担心兼容性. 对于Compose来说, 至少和View的结合是无缝的. (目 ...
- 【原创】Ingress-Nginx-Controller的Metrics监控源码改造简析
一.背景 目前我们的生产环境一层Nginx已经容器化部署,但是监控并不完善,我们期望其具有Ingress-Nginx-Controller组件上报监控的数据.这样可以建立请求全链路的监控大盘.有利于监 ...
- excel VBA构造正则函数(单参数)
Function zhengze(Rng As Range) Set regx = CreateObject("vbscript.regexp")With regx .Gl ...
- 乘风破浪,Java遇见OpenJDK GA(Build By Microsoft),即将晋升为Azure云管理服务默认JVM
什么是Microsoft Build of OpenJDK Java Development Kit (JDK) 是Sun公司(已被Oracle收购)针对Java开发员的软件开发工具包.自从Java推 ...