mysql5.5版本以上默认使用Innodb存储引擎。
页是Innodb磁盘管理的最小单元,页里面存放的是多个行数据(默认大小16k)。
页(Page)可以为空,也可以填充一半,也可以填充100%,但是不能只放一个数据,这样和单纯的链表没有任何区别。当然,如果行数据过长,也可能会发生行溢出,页中的数据排列顺序是根据主键排列。
主键优化
首先先说两种情况: 页分裂和页合并。
页分裂
什么情况会发生页分裂? 当乱序插入的时候可能发生。
我们先看看顺序插入:因为数据页存放的数据是根据主键排列顺序存放的,所以来一个数据只要往后存进去就行。
我们再来看看乱序插入:我们要知道一个前提,尽管我们是乱序插入,但是数据页数据的排列顺序是根据主键的排列。这里涉及主键的三种方式:①聚集索引②第一个唯一索引③隐藏主键。
因为是乱序插入,当ID为50的数据想插入的时候,它会去找应该插入的数据页的50%的位置,然后截取后半段(或前半段)到新的数据页(3号数据页)中。
插入之后。这个过程就发生了页分裂,一个页中的数据被分开了。。。
随后改变数据页的相对位置,因为我们要保证数据页的顺序为主键的顺序排列。
一号数据页后面是三号数据页再后面是二号数据页。。。
页合并
什么时候可能发生页合并? 当删除数据的时候。
我们知道当我们删除一行数据的时候,它只是逻辑删除,物理空间没有被删除(只是被记录了删除,同时它的空间可以被其他数据使用)。当一个数据页中被删除的数据达到了一定的阈值(默认50%),则Innodb会自动去查看相邻数据页,看看是否可以合并成一个数据页以优化空间。。
因为二号数据页中被删除的数据达到50%,所以会向前,向后查看是否能合并成一个数据页。
设置阈值:通过MERGE_THRESHOLD 设置合并页的阈值,在创建表或创建索引的时候使用。
主键设计原则
适当降低主键的长度。因为二级索引的叶子节点存放的是当前主键数据,如果长度过大,同时一个页的大小是固定的,则一个页存放的行数据就少,同时一个表结构中二级索引可以有多个,一旦二级索引过多,则会大大增加磁盘空间,而且在搜索的时候会增加磁盘IO。
乱序插入可能会存在页分裂的现象。
// UUID是无序的,同时长度比较长。