主键优化
数据组织方式 在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table)简称IOT
页分裂 1区的大小是1M,1区有64个页,1页的大小是16k。页可以为空,也可以填充一半,也可以填充100%。每个页包含了2~n行数据,如果 一行数据过大,会导致行溢出。每个页的行数据会根据主键排列
聚集索引的B+树的底部节点索引是双向指针,存储的是一整行数据,并且数据大小是从左到右,即左小右大。插入的顺序可以是顺序或乱 须,但是存储进去之后必须是以左小右大的顺序来存储
主键顺序插入 当数据在一个页中已经写满了或写不下,就会申请第二个页继续写。这两个页之间会维护一个双向指针。同理申请更多页的话,页之间也会 有双向指针
主键乱序插入(页分裂) 假如当已有的两个页都写满了数据,此时需要再插入'一个数据',那么就会申请第三个页,但是由于是乱序插入,要插入的'这个数据'的大小是 在'第一个页的末尾'和'第二个页的头部'之间,那么'这个数据'怎么插入进去,申请的第三个页怎么使用,如下:####################### 第一个页的50%后的数据会全部转移到第三个页,然后要插入的'这个数据'会在第三页的转移数据后的位置插入,然后调换第一页和第三页的位置, 在调换页的时候,内部会重新设置链表指针,也就是第一页指针指向的不是第二页,第一页指针指向的是第三页。这种现象称为页分裂 总结: 当主键乱序插入的时候,就可能会出现也分裂
主键乱序插入可能会导致页分裂,所以在SQL优化中,我们在插入数据时,建议是顺序插入
删除数据(页合并) 当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。当我们要删除某个页的 超过50%数据的时候,InnoDB会开始寻找最靠近的页,看看是否可以将两个页进行合并(找前面的页跟自己合并,或找后面的页跟自己合并),以优化空间使用
页合并(自己这个页,跟前面或后面的其中一个页合并),举例如下
1、当前面那个页只用了10%,自己的页被删了超过50%目前只用了10%,那么前面那个页就会跟自己的页合并为一个页
2、当后面那个页只用了30%,自己的页被删了超过50%目前只用了10%,那么后面那个页就会跟自己的页合并为一个页
3、当前面那个页只用了80%,自己的页被删了超过50%目前只用了30%,不可以合并,原因是80%+30%>100%
4、当后面那个页只用了80%,自己的页被删了超过50%目前只用了30%,不可以合并,原因是80%+30%>100%
合并之后,必然会有页空闲,空闲的页不会被回收,只是这个页里面没有数据,等待着下一批数据的进来 页合并的阈值MERGE_THRESHOLD也就是50%是可以自己设置的,默认是50%,在创建表或者创建索引时指定、
通过上面的学习,我们知道主键插入的顺序尽量使用顺序插入,以及在删除数据时出现的页合并。
主键索引的设计原则如下:
1、满足业务需求的情况下,尽量降低主键的长度 原因:主键索引(唯一)会在二级索引(多个)的B+树底部叶子节点上存储,如果主键索引长且二级索引多,会占用大量磁盘空间,在搜索的时候还会浪费大量的磁盘IO
2、插入顺序时,尽量选择顺序插入,选择使用auto_increment自增主键
3、尽量不要使用UUID做主键或者是其他自然主键,如身份证号
4、业务操作时,避免对主键的修改