前言
由于cpu对数据的读取方式,所以采用页来作为单位,索引来提高查找效率。
innodb把数据划分成一页一页,以页作为磁盘与内存交互的基本单位
这些页跟页之间的关联、以及页跟数据的关联、数据查找、插入……采用索引
innodb支持行锁、并发安全性高
从磁盘把数据放内存,cpu再处理
局部性原理
cpu把数据从磁盘读到内存中,一条一条取,会比较费时
会多取数据
innodb将数据分成一页一页,磁盘与内存的交互单位为页,一页的大小为16kb
cpu最少要从磁盘取16k的数据放到内存,
写时,至少要写一页的数据到磁盘,
取这一行的的一页数据16kb到内存
提高执行速率
取1,1个字节,可能马上要取相邻的数据,把数据跟相邻的一起取放内存,下次如果正好,就可以从内存拿
每次多取,取1页,4kb
innodb:是16kb
取这一行的一页的数据16kb,放内存中被查
不同类型数据:不同页
用户记录(从空闲空间取一部分作为用户记录)
空闲空间
页directory
我们看到的表是逻辑上的
页结构
SHOW GLOBAL STATUS LIKE 'Innodb_page_size';
16384 就是16kb
每次插入数据,会将free space 一部分划分成user recoder
行格式
数据存储在innodb有行格式
所以我们每个数据的字段不能存到65535,要留空间给行格式
一行的数据超过1页 16kb,就会行溢出
compact:
变长字段长度列表
存变长字段的真实空间
null标记
把可以为null值的列统一存起来,用二进制表示值是否为null
如果不存在允许为null的列,则,null标记不存在
记录头信息
记录记录在堆的位置,下一行记录的位置等信息
隐藏列
行id:如果没有定义主键,就采用行id
事务id
回滚指针
compact行格式:
变长字段长度列表:记录变长的变量的当前的空间,按字段的顺序记录
null标志位:代表是否存数据
varchar(20) 是可变长的,最多存20个字符
存几个字符就是几个字符占的空间,只要不超过20,一个字符3个byte
一行最大是65535,但是如果有变长,可以存null,要减去1+2(还要行的格式)
一页放不下一行:行溢出
行溢出
解决:
所以要在这一页上:
compact:存部分数据+下一页地址
dynamic、compressed
第一页只存一行下一页地址:使得行数据更多,不只有只存一种数据
这样查找下一行时,就不会一直下一页下一页找下一行,导致一行影响其他行的查找
插入后为什么自动排序了
排序的好处
采用链表的方式来存储,因为不连续存储插入跟删除开销小,
可以采用其他方法来改善查找效率,
但是采用连续内存,就不好改善插入跟删除的效率
为改善链表查找,每一页有页目录跟链表,把链表分成多个组,
页目录存不同组的头结点(链表结点的地址、主键最小值)
同时可以采用二分法查找页目录
目录再存页目录的页号跟这一页的最小主键
可以早些停止查询
链表的查询比较慢,所以对数据进行分组,再把一组的头结点存在页目录中,提高查询效率
查找页目录时可以采用二分法
当数据很多,需要很多页,需要
一个目录页
页跟页是链表(逻辑相邻,物理不相邻)
采用key-value(k是value页中主键最小的值)
存储
每一页:页目录、链表
对链表分组,每一组的主键id最小值存在页目录
页与页:双向链表
再来一页:页地址(页号)、每一页的最小主键值值
一页有多个数据,主键就是索引,结点就是页
索引
通过缩小数据的查找范围、排序来提高查询效率
原理采用b+树来对数据进行排序跟分段,使得我们可以分段查询
主键索引
数据跟索引聚在一起
辅助索引
除主键外的索引就是赋值索引
对要加索引的字段进行排序
(按照字段进行排序,排序的方法采用的是b+树)
字符集也有他的比较规则(字符串转数字再排序)
辅助索引可以相同
从辅助索引找到主键
最左前缀原则:通过辅助引索来找主键