InnoDB 溢出列
MySQL InnoDB 使用页(16 KB)来进行磁盘和内存的交互。如果某张表一行超过 16 KB 会发生什么?
它会把数据塞到下一页吗?答案必然是否定的。因为如果每一行占用几十甚至几百 KB 的话,不停的塞入下一页就会造成叶子结点的上一层只能记录非常少的索引。整个 B+ 树索引无疑就成了笑话。
实际上,在 COMPACT 和 REDUNDANT 的行格式中,对于这种“大数据”,MySQL 的设计者并不是针对这一行做了处理,而是针对行的每一列进行了特殊的处理。当前记录的某一列只会记录该列的一部分数据。把剩余的数据存储到其他的页中,然后当前列利用 20 字节的数据存储占用的字节数以及下一页对应的地址。如此一来,我们的索引就不会出现异常问题了。
在实际页面中,实际页只会存储该列的前 768 字节数据以及 20 字节(页面)的数据。我们会把这列数据叫做溢出列(off-page 列),这些存储额外信息的页面也叫做溢出页(和存储正常数据的页面类型不同)。如 VARCHAR,TEXT,BLOB 类列数据存储都有可能成为溢出列。
注意:一条记录可能会有多个溢出列。
MySQL 规定了一页至少有两行数据(溢出页没这个规定)。除去页和行的额外信息,如果两行相加大于 16 KB 就会出现溢出列。MySQL 会不断溢出最长的列直到能存储下数据为止。这里也没有必要那么的精确的计算,开发者只要知道如果一行中某个列存储的数据较多,这一列就会成为溢出列。
项目开发的过程中,建议在查询时只查询需要的列,对于可能溢出的列又用不到就不要去查了。因为我们还要去查溢出页对应的数据。