MySQL InnoDB 索引组织表 & 主键作用
InnoDB 索引组织表
一、索引组织表定义
在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table IOT)。
在InnoDB存储引擎中,每张表都有个主键(Primary key),如果在创建表时没有地定义主键,则InnoDB存储引擎会选择表中符合条件的列去创建主键。
条件:
1. 首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键。
2. 如果不符合上述条件,InnoDB存储引擎自动创建一个6字节大小的指针。
当表中存在多个非空的唯一索引的时候,InnoDB存储引擎会根据建表时所创建的第一个非空唯一索引作为主键。
二、案例
创建test表
CREATE TABLE test( a INT NOT NULL , b INT NULL , c INT NOT NULL , d INT NOT NULL , UNIQUE KEY(b) , UNIQUE KEY(d) , UNIQUE KEY(c) )
初始化数据
INSERT INTO test SELECT 1,2,3,4; INSERT INTO test SELECT 5,6,7,8;
通过以下语句可以判断表带主键值(_rowid为主键)
select *,_rowid from test;
虽然b字段索引的顺序在d之前,但由于b字段允许空值,所以依次往下排即选取d字段为主键。
ps,如果为联合索引,那么久无能为力了!
三、为什么需要唯一主键呢?
主键(primary key) 一列(或一组列),其值能够唯一区分表中的每个行。 唯一标识表中每行的这个列(或这组列)称为主键。没有主键,更新或删除表中特定行很困难,因为没有安全的方法保证只设计相关的行。简单的说主键的目的在于索引。
InnoDB引擎使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)。
1. 如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。如下图所示:
这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时也不需要移动已有数据,因此效率很高,也不会增加很多开销在维护索引上。
2. 如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间。此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。
若有不恰当之处,还望指教,谢谢!
参考书籍:
[1]. MySQL技术内幕:InnoDB存储引擎