mysql 深入(InnoDB)
文章目录
0、引入
局部性原理:
从磁盘取一个数据的时候,会把相邻的数据也取出来。(因为是可能不久之后你就需要相邻的数据了,所以也先从磁盘取出来,放到内存中)
取多少:页单位,4KB
mysql:虽然当前可能只是需要取一条数据,但是他也会取出其他数据放到内存中去,大小是:16384/1024 16KB(页单位)
相当于数据存在页里面
1、页结构
File Header:所有类型的页共用的头部
Page Header:数据页专用的头部。当前举例是数据页
User Record:用户记录(存储)
Free Space:空闲的空间(存储)
- 插入数据之后会在Free Space中划出一块空间到User Record中
Page Directory*:页面目录:页面中某些记录的相对位置
- 会把部分行数据分组,存每一部分开始的主键
- 目录页(存页号)、页目录(存主键)要分清
File Trailer:文件尾部
2、行结构
InnoDB行格式:
Compact、Redundant、Dynamic(默认是这个行结构)和Compressed
Compact
变长字段长度列表:统计可变长字段内容对应的字节(分块、按字段顺序存储)
NULL标志位:标志每一位是不是为空
例子:
create test( c varchar(65535) ) CHARSET = ascii ROW_FORMAT = Compact
有报错
- 原因:每一行最大的占用空间确实是65535个字节,但是由于c是可变长且需要标志是否为空,所以需要在每一行开辟出变长字段长度列表和NULL标志位。所以sql不能够执行成功。
65532就可以了
变长1字节,NULL2字节
记录头信息:里面有个字段:next_record:指向下一行的地址
行溢出(Compact、Dynamic)
假如一个页存不下一整行的数据,行结构为Compact、Redundant时
- 会把一部分数据和下一页的地址(20个字节)存在第一页,其他数据再放在第二页,以此类推。
而Dynamic则是会
- 在第一页存放下一个数据页的地址,不放数据。
Compressed
- 会用压缩算法对数据进行压缩
3、索引
-
myIsam:插入数据后若是不加索引,查出来的顺序就是插入的默认顺序(堆表)
-
InnoDB:会按照主键顺序查出来,其实已经排好序了(主键是索引)
1、页结构存储数据
- 若是一页存不下,可以分开多个页,但是也需要目录页记录页号,方便查询。
2、目录页
若是要查找7_455g,要先定位到第二页,才会更快地找到那一行。所以需要目录页,记录页结构的信息(页号可以理解为内存地址)
假设页面1页号为100,页面2页号为200
上一个目录页记录的
- 1\100:就是页号100的页面最小主键的值
- 5\200:就是页号200的页面最小主键的值
目录页中也有页目录,也可以方便找到所需要的下一层的页号,内部结构和最底层的树是一样的。也是链表,也有页目录,只是最底层的链表存的是行结构,目录页存的是页地址或者页信息。
其实这个就是b+树结构
3、B树和B+树:
- B+树
- B树
B树:B树和平衡二叉树稍有不同的是B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引技术里大量使用者B树和B+树的数据结构,让我们来看看他有什么特点
- 规则:
(1)排序方式:所有节点关键字是按递增次序排列,并遵循左小右大原则;
(2)子节点数:非叶节点的子节点数>1,且<=M ,且M>=2,空树除外(注:M阶代表一个树节点最多有多少个查找路径,M=M路,当M=2则是2叉树,M=3则是3叉);
(3)关键字数:枝节点的关键字数量大于等于ceil(m/2)-1个且小于等于M-1个(注:ceil()是个朝正无穷方向取整的函数 如ceil(1.1)结果为2);
(4)所有叶子节点均在同一层、叶子节点除了包含了关键字和关键字记录的指针外也有指向其子节点的指针只不过其指针地址都为null对应下图最后一层节点的空格子;
B树和B+树的区别
- B+树把B树中非叶子结点的data移到了叶子结点,好处:节省了很多空间
- B+树在叶子结点处使用了指针连接(MySql底层是双向指针),对范围查找十分友好,(从小到大),若是B树需要范围查询就只能多次从根节点遍历,B+树只需要执行一次即可。
mysql底层设置B+树,索引占用的空间大约8B BigInt类型(主键索引类型的大小),空白的是下一个节点在磁盘上的地址6B(底层源码可知),mysql设置的B+树,一个大节点(一页)大约是16384B约等于16KB(就是一页,结合上文的页结构),就是说索引(索引加下一个节点的地址 = 8+6)14B,一个大节点放满之后能放1170个。
4、MyIsam 底层通过索引查询的过程
- MYD文件:MyIsam表的数据
- Frm:表结构信息相关
- MYI:index 放索引的地方,Col1是索引,在MYI文件里面用B+树维护
MyIsam过程:
- 1、先判断sql语句的过滤条件是不是索引字段,是的话,先去MYI文件中按照B+树结构定位索引
- B+树查询过程:先根节点,找到目标索引或者指针,找到叶子节点之后,把整个叶子节点加载到内存,在内存中查找到30索引这个元素的位置。
- 2、再把30这个行的磁盘文件地址(指针),这个指针,在MYD文件中找到对应行的位置(也在内存中)
5、 InnoDb底层通过索引查询的过程
- Frm文件:表结构
- ibd文件:相当于MYD+MYI文件
叶子节点data里面:存的是索引所在行的其他所有列的数据,和MyIsam不同,MyIsam里面存的是在磁盘中位置的地址(一个指针)。
主键索引是主索引,其他的都是辅助索引
- 非聚集索引:MyIsam主键索引(稀疏索引、非聚簇索引) 索引MYI文件,数据MYD文件
- 聚集索引:Innodb主键索引(聚簇索引)
6、Q:为什么Innodb表一般都要建立主键,并且是整数自增的情况
A:因为Innodb建表之后在底层会使用B+树来维护,如果不是没有主键的话:
- 1、Innodb会自动查找一列没有重复的列来作为主键,然后用B+树维护
- 2、若是找不到的没有重复的列,Innodb会在后台新建一个隐藏列,会维护唯一性,用隐藏列来维护整张表的所有数据
所以推荐自己建立主键,减少mysql负担。
7、为何要自增?
A:uuid是字符串不是整型,也不是自增
1、需要做很多次比对,uuid比对需要一个一个比对,转ASCII等,数字比对比字符串比对快
2、整型占几个字节,uuid占得多,节省空间,结合上文的页结构思考**(不需要新增页结构,每个页结构可以存储更多的行结构。)**
3、uuid不是自增,可能会破坏之前的树结构,如果是自增的话只需要在索引树的最右边加上一个页结构就可以了。
8、 Hash索引(快,占内存(要做hash),不适合范围查找):
对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。