【mysql】- 索引简介篇
简介
- 我们都知道
mysql
使用存储引擎的是InnoDB,InnoDB使用的索引的对应的数据结构是B+
树
结构图:
- 如上图所示,我们实际用户记录是存放在
B+
树的最底层的节点上,这些节点也被称为叶子节点
或者叶节点
,其余用了存放目录项
的节点称为非叶子节点
或者内节点
,最上边的节点为根节点
。 InnoDB
是使使用页
来作为管理理存储空间的基本单位,也就是最多能保证16KB
的连续存储空间,而随着表中记录数量量的增多,需要非常大的连续的存储空间才能把所有的目录项都放下,这对记录数量非常多的表是不现实的目录项
两个列是主键
和页号
,与用户记录
差不多,为了和用户记录
进行区分,我们把这些用于表示目录项的记录称为目录项记录
,区分方法为:- 通过记录头信息的
record_type
属性:- 0:普通用户记录
- 1:目录项记录
- 2:最小记录
- 3:最大记录
- 通过记录头信息的
- 其设计者规定了最下边的那层,也就是存放记录的那层为第
0
层,之后依次往上加。 - 现在以查找主键为
20
的记录为例,采用二分法进行数据查询- 首先到存储
目录项记录
的页,也就是页33
中通过二分法快速定位到对应的目录项,因为1
<20
<320
,所以定位到对应记录所在的页就是30
; - 此时
12
<20
<209
,所以定位到对应的记录所在的页就是页9
; - 再到存储用户记录的
页9
中根据二分法快速定位到主键值为20
的用户记录。
- 首先到存储
扩展,为什么不用
B
树,而采用B+
树呢?
- 根据
B
树的特点是每个节点都是存储记录的,那么就会存在一个问题,假如同样的一个深度的树,B
树会比B+
树的页要大很多,同样一页16k
的数据,加载B+
树的记录的范围会比B
树的范围要大,那么磁盘IO的操作次数显然是B
树要更多一些。
索引的分类
- 聚簇索引
- 使用用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
- 页内的记录是按照主键的大小顺序排成一个单向链表。
- 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表。
- 存放目录项记录的页分为不不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个双向链表。
B+
树的叶子节点存储的是完整的用户记录。
- 使用用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
大家有木有发现,上边介绍的
聚簇索引
只能在搜索条件是主键值时才能发挥作用,因为B+
树中的数据都是按照主键进行行排序的。那如果我们想以别的列列作为搜索条件该咋办呢?难道只能从头到尾沿着链表依次遍历记录么?此时便有了二级索引
。
- 二级索引(辅助索引)
- 如图
- 我们可以多建几棵
B+
树,不不同的B+
树中的数据采用不不同的排序规则。 - 这个
B+
树与上边介绍的聚簇索引有几处不不同:- 使用记录
c2
列的大小进行行记录和页的排序,这包括三个方面的含义:- 页内的记录是按照
c2
列的大小顺序排成一个单向链表。 - 各个存放用户记录的页也是根据页中记录的
c2
列大小顺序排成一个双向链表。 - 存放目录项记录的页分为不不同的层次,在同一层次中的页也是根据页中目录项记录的
c2
列大小顺序排成一个双向链表。
- 页内的记录是按照
B+
树的叶子节点存储的并不不是完整的用户记录,而只是c2
列 +主键
这两个列列的值。- 目录项记录中不不再是
主键
+页号
的搭配,而变成了了c2
列+页号
的搭配。
- 使用记录
- 以查找
c2
列的值为4
的记录为例,查找过程如下:- 确定
目录项记录
页- 根据
根页面
,也就是页44
,可以快速定位到目录项记录
所在的页为页42
(因为 2 <4 < 9 )。
- 根据
- 通过
目录项记录
页确定用户记录
真实所在的页。- 在
页42
中可以快速定位到实际存储用户记录的页,但是由于c2列列并没有唯一性约束,所以c2
列列值为4
的记录可能分布在多个数据页中,又因为2 < 4 ≤ 4
,所以确定实际存储用户记录的页在页34
和页35
中。
- 在
- 在真实存储用户记录的页中定位到具体的记录。
- 到
页34
和页3
中定位到具体的记录。
- 到
- 但是这个
B+
树的叶子节点中的记录只存储了c2
和c1
(也就是主键)两个列,所以我们必须再根据主键值去聚簇索引中再查找一遍完整的用户记录。
- 确定
- 我们可以多建几棵
上面的操作其实就是一个
回表
,整个完成的查找需要用到2棵B+
树。那为什么需要回表
操作呢?直接把完整的用户记录放到叶子节点 不不就好了了么?
- 原因:
- 太占用地方,相当于每建立一棵
B+
树都需要把所有的用户记录再都拷贝一遍,这就有点太浪费存储空间了了
联合索引
我们也可以同时以多个列的大小作为排序规则,也就是同时为多个列列建立索引,比方说我们想让
B+
树按照c2
和c3
列的大小进行排序,这个包含两层含义:- 先把各个记录和页按照
c2
列进行排序。 - 在记录的
c2
列列相同的情况下,采用c3
列进行排序。
示意图如下:
- 先把各个记录和页按照
如图所示,我们需要注意一下几点:
- 每条目录项记录都由
c2
、c3
、页号
这三个部分组成,各条记录先按照c2
列列的值进行排序,如果记录的c2
列相同,则按照c3
列的值进行排序。 B+
树叶子节点处的用户记录由c2
、c3
和主键c1
列组成。
- 每条目录项记录都由
千万要注意一点,以
c2
和c3
列的大小为排序规则建立的B+
树称为联合索引
,它的意思与分别为c2
和c3
列分别建立索引的表述是不不同的,不不同点如下:- 建立
联合索引
只会建立如上图一样的1棵B+
树。 - 为
c2
和c3
列分别建立索引会分别以c2
和c3
列的大小为排序规则建立2棵B+
树。
- 建立
总结:
- 1.对于
InnoDB
存储引擎来说,在单个页中查找某条记录分为两种情况:- 以主键为搜索条件,可以使用
Page Directory
通过二分法快速定位相应的用户记录。 - 以其他列列为搜索条件,需要按照记录组成的单链表依次遍历各条记录。
- 以主键为搜索条件,可以使用
- 2.没有索引的情况下,不不论是以主键还是其他列列作为搜索条件,只能沿着页的双链表从左到右依次遍历各个页。
- 3.
InnoDB
存储引擎的索引是一棵B+
树,完整的用户记录都存储在B+
树第0
层的叶子节点,其他层次的节点都属于内节点 ,内节点里存储的是目录项记录 。 InnoDB 的索引分为两大种:- 聚簇索引
- 以主键值的大小为页和记录的排序规则,在叶子节点处存储的记录包含了表中所有的列。
- 二级索引
- 以自定义的列的大小为页和记录的排序规则,在叶子节点处存储的记录内容是
列
+主键
。
- 以自定义的列的大小为页和记录的排序规则,在叶子节点处存储的记录内容是
- 聚簇索引
- 4.
MyISAM
存储引擎的数据和索引分开存储,这种存储引擎的索引全部都是 ⼆二级索引 ,在叶子节点处存储的是列
+页号
。
- 1.对于
【mysql】- 索引简介篇的更多相关文章
- 初识mysql索引 - 小白篇
:接触mysq也有两年左右的时间了,但是对该数据库的理解自认还比较初级,看过很多文章,也看过一些相关的书籍,依然小白....(这里个人总结是两点主要原因:1.对mysql的学习大部分都是源于看一些杂七 ...
- Mysql 索引 简介
Mysql索引 索引的分类 索引的创建 索引的注意事项 什么是索引 索引是存储引擎用于快速查找记录的一种数据结构. 索引由数据库中一列或者多列组成,作用是提高表的查询速度. 索引的优点,提高检索数据的 ...
- MySQL索引——总结篇
MySQL索引 MySQL索引 数据库的三范式,反模式 零碎知识 索引 索引原理 B Tree索引 B+Tree索引 B Tree 与 B+Tree的比较 聚集索引和辅助索引 聚集索引的注意事项 索引 ...
- MySQL索引简介(转)
一.为什么用索引例:先假设有一张表,表的数据有10W条数据,其中有一条数据是nickname='css',如果要拿这条数据的话需要写的sql是 SELECT * FROM award WHERE ni ...
- MySql索引简介
从"找"到B+树 索引是用来查找的. 折半查找是一种很优秀的方式.适合于 范围查找,固有缺点就是需要元素是有序的.二叉搜索树就是对折半查找的一种基础的实现. 但二叉搜索树当遇到特殊 ...
- Mysql高手系列 - 第22篇:深入理解mysql索引原理,连载中
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第22篇. 背景 使用mys ...
- MySQL中的索引简介
MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 一. 索引的优点 为什么要创建索引?这是因为,创建索引可以大大提高系统的查询性能. 第一.通过创建唯一性索引,可以保 ...
- Mysql索引(一篇就够le)
我想很多人对mysql的认知可能就是CRUD(代表创建(Create).更新(Update).读取(Retrieve)和删除(Delete)操作),也不敢说自己会用和熟悉mysql,当然我就是其中一个 ...
- 「 MySQL高级篇 」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
随机推荐
- redis编译报错总结
redis编译报错总结: 1.不能编译没有GCC 编译工具安装报错:问题1:make时可能会报如下错误cc -c -std=c99 -pedantic -O2 -Wall -W -g -rdyna ...
- 虚拟机VMware克隆之后网络不可用的解决办法
现在有两台虚拟机,113是111的克隆,要让113能够使用,需要做下面的修改 5.解决办法5.1.修改克隆后机器(B机器)70-persistent-net.rules文件内容 对克隆后机器(B机器) ...
- Python初识类与对象
Python初识类与对象 类与对象 世界观角度分析类与对象 类是一个抽象的概念,而对象是一个实体的存在,对象由类创造而出,每个对象之间互相独立互不影响,一个对象可以同时拥有多个类的方法,实例化就是通过 ...
- 【状压dp】Bzoj1294 围豆豆
题目 Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别为每颗豆子的分值. 接着N行有一个N×M的字符矩阵来描述游戏矩阵状态,0表 ...
- Java 从入门到进阶之路(二十七)
在之前的文章我们介绍了一下 Java 中的 集合框架中的Collection,本章我们来看一下 Java 集合框架中的 Map. Map 接口定义的集合又称查找表,用于存储所谓“Key-Value” ...
- sql:主键(primary key)和唯一索引(unique index)区别
主键一定是唯一性索引,唯一性索引并不一定就是主键. 所谓主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引. 因为主键可以唯一标识某一行记录,所以可以确保执行数据 ...
- 洛谷 P1215 【[USACO1.4]母亲的牛奶 Mother's Milk】
这道题\(DFS\)就好了,六种情况,\(ab,ac,ba,bc,ca,cb\),我们直接枚举就可.什么?这样不会结束?用一个\(vis\)数组判断走过没有就可以了.最后排序输出即可. \(code: ...
- 堆/题解 P3378 【【模板】堆】
概念: 堆就是一颗二叉树,满足父亲节点总是比儿子节点大(小).因此,堆也分为大根堆和小根堆,大根堆就是父亲节点比儿子节点大,小根堆正好相反.注意加粗的地方,是每一个节点哦!!!!! 还是直接看例题吧, ...
- Linux中清空docker容器日志
新建文件docker-clear-log,放在/usr/local/bin/目录下,文件内容如下: #!/bin/bash -e if [[ -z $ ]]; then echo "No c ...
- 【2003、2004 NOIp 入门组错题报告】
2003: T4: 题目大意: 讲这么多话,其实就是求比当前序列大的序列中第m小的一个.可以每次找出比当前序列大的最小的一个序列.我们可以从后往前扫描,当当前这个数比后一个数小时,我们把它与它后面的 ...