1、行溢出
-
行溢出(Row Overflow),是当数据库的行中数据的大小超过了数据库页的最大容量限制时(默认 16K),超出的部分会被存储到额外的页上,同时会附加一个指针指向对应数据页。这个过程就是所谓的 "行溢出"。
-
行溢出触发条件的影响因素包括:行格式、页大小、索引值等。
-- 字段大小超过页容量的一半(也就是8KB)时,会触发行溢出
-- 单行数据多个字段大小总和超过了页大小的阈值(一般是75%),会触发行溢出
-- 一个二级索引元素值太大,导致无法在页中完全存储除了索引外的其余数据,会触发行溢出 -
行溢出机制的优点
-- 灵活性: 行溢出机制为大字段提供额外空间,不用更改表结构
-- 存储效率: 溢出的数据只占用实际需要的空间,避免在固定行的大小的表中存储的浪费
-- 自动管理: 无需人工干预,InnoDB会保证对行的读写操作的原子性和一致性 -
行溢出机制的缺点
-- 间接导致页分裂:...间接导致页分裂(多种情况)
-- 增加内存消耗: 缓冲池中会存储更多的数据页
-- 性能降低: 对于分散在多个页的数据的检索会更慢
-- 增加IO消耗: 在写入操作中,对于行溢出需要更多的 IO 操作来处理数据
-- 索引限制: 行溢出会影响索引的的正常使用 -
如何避免行溢出
-- 合理设计表,尽量避免字段冗余、低效
-- 选择合适的字段类型,并给出合理的字段长度
-- 合理使用索引
-- 定时监控和分析,合理调整配置,如缓冲池大小、页大小
-- 对于某些频繁更改的大字段考虑是否有别的存储方案
2、页分裂
-
页分裂(Page Split) 一个已满或接近满的数据页需要插入新记录时。数据库不能改变现有的记录 来容纳新记录,因此会将该页的记录分割存到新的一页,并在新旧数据页之间创建指针
-
页分裂的触发条件
-- 当插入行的行数据大小超过页当前可用空间,且导致当前页使用率超过原有大小的1.5倍
-- 非自增主键,在已插入页的行的ID中间插入新的逐渐ID,违反索引的顺序性,会页分裂进行重 新排序。比如已有ID 1 和 3,接着插入ID 2。 -
页分裂机制的优点
-- 灵活性和扩展性: 页分裂让数据库适应变化的数据需求,保持数据结构的完整性和稳定性
-- B+树结构维护友好: 通过对索引页进行分裂,保持B+树的平衡度,有利于数据的快速查找
-- 减少数据页碎片: 页分裂可以重新组织数据,减少数据碎片化
-- 自动管理: 无需用户干预,透明处理空间不足的问题 -
页分裂机制的缺点
-- IO操作增加: 页分裂过程中,数据的移动和共享涉及到额外的磁盘IO操作,会降低性能
-- 磁盘碎片增加: 频繁的页分裂会导致磁盘碎片的产生,会降低数据检索性能。并且可能导致 子页面和主页面不在同一物理存储位置,增加访问时的跳转,降低性能
-- 牵扯其他操作: 页分裂受页大小的限制,对于很大的数据不能完整存储到一个页中,需要 行溢出。还可能触发索引重建等操作 -
如何避免页分裂
-- 合理创建、优化索引,避免创建过多索引、尽量避免乱序插入主键索引
-- 新数据采用批量插入,减少单次操作导致的分裂
-- 定期维护重建索引
-- 减少长事务
-- 有条件也可以硬件升级
-- 合理分区分表 -
需要注意的是,不能也不应该完全避免页分裂机制,适当的页分裂对数据库来说是很重要的。应该 高效管理页分裂以避免性能问题