一行记录的存储格式:
mysql的数据存放在哪个文件?
进入/var/lib/mysql找到对应的mysql文件:
1.db.opt 存储数据库默认字符集和校验规则
2.xx.frm保存表结构
3.xx.ibd保存表数据
表空间文件的结构:
行:数据库表中的纪录都是按行来存放的
页:InnoDB的数据是按页为单位来读写的,默认的每个页的大小为16kb,
区:连续的64个页会被划为一个区
段:包含区
InnoDB的行格式有哪些:
行格式:就是一条记录的存储结构
redundant是很古老的行格式
compact是一种紧凑的行格式
dynamic和compressed都是基于compact改进的
所以一般弄懂compact行格式就行了
compact行格式长啥样?
记录的额外信息:变长字段长度列表,null值列表,记录头信息
变长字段长度列表:保存变长字段的真实数据占用的字节数,且是逆序存放的,逆序存放是为了提高cpu cache的命中率,当没有变长字段时就没有变长字段长度列表了。
null值列表:二进制为1时代表值为null,为0则代表列的值不为null
记录头信息:包含内容很多
varchar(n)的n最大取值多少?
如果字符集是ascii,则一个数一个字节,一行记录最大容量65535字节,但是还包含变长字段字节数和null值所占字节数,即-2-1,65535-2-1=65532。
行溢出怎么办
InnoDB会将其转到溢出页。
char和varchar
存储对比:
char和varchar都会存储字符串长度
对于char(n)字段,如果实际存储长度小于n字节,会填充空格到n个字节
性能对比:
char填充空格可能会导致浪费存储空间,进而导致性能下降
但是有些时候char还是比较有用的,比如某个字段的最大长度是100字节,那么用char(100)好一点
数据页
数据页包括7个部分:
数据页有一个页目录:
InnoDB里的B+树的每个节点都是一个数据页:
聚簇索引和二级索引:
聚簇索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚簇索引的叶子节点
二级索引的叶子节点存放的是主键值,而不是实际数据。
buffer pool
就是缓冲池,InnoDB存储引擎的,用来提高数据库的读写性能
buffer pool以页为单位进行缓冲,缓冲池大小是128M,可自己调整大小
管理缓冲页(innodb通过3种链表来管理缓冲页):
free list(空闲页链表):管理空闲页
flush list(脏页链表):管理脏页
LRU list:管理脏页加干净页,将最近且经常查询的数据缓存在其中,而不常查询的数据就淘汰出去。
innodb对LRU算法做了一些优化:
本来的LRU算法就是把要用的放在头部,不常用的会逐渐到尾部被淘汰掉,这里改进的是将LRU链表分为young和old两个区域,加入缓冲池的页,优先插入old区域,页被访问时才进入young区域,目的是为了解决预读失效的问题。当页被访问且在old区域停留超过一定时间(默认1s)才会将页插入young区域,否则插入old区域,目的时为了解决批量数据访问,大量热数据淘汰的问题。
在开启了慢sql监控后,偶尔出现用时稍长的sql,是脏页刷新到磁盘时导致的数据库性能抖动,如果在短时间内出现这种现象就需要调大buffer pool空间或redo log日志的大小。
change buffer
change buffer就是存在与buffer pool的一个东西,可以节省随机读磁盘的IO消耗,只有普通索引可以使用change buffer,唯一索引不能使用change buffer。change buffer一般是在内存中没有数据页的时候用的,相当于一个暂时的更新地方,当下次调用数据页的时候,将真实的数据页根据change buffer进行更新。
redo log是节省随机写磁盘的IO消耗。