主键
主键每一行都应该有能够唯一标识自己的一列。
主键(primary key),其值能够唯一区分表中的每一行数据。如果没有主键的话,更新或者删除表中的特定行就会很困难,因为没有安全的方法能够唯一标识这一行数据。
虽然并不是总需要主键,但是我们都应该保证每个表都有主键,以便于以后数据操纵和管理。
主键的条件
表中的任一一列都能够作为主键,但是作为主键有以下几个条件:
1、 主键值不能重复
2、主键值不能为NULL
其上两个条件是mysql主键的强制要求,但我们最好养成下面几个好习惯:
- 不更新主键的值
- 不重用主键列的值
- 不在主键列中使用可能会更改的值
主键的作用
现在mysql几乎应用的都是InnoDB存储引擎。主键的作用还有一个就是索引。
无特殊需求下 Innodb 建议使用与业务无关的自增 ID 作为主键
- InnoDB引擎使用聚集索引,数据记录本身被存于主索引(B+树)的叶子节点上。这就要求同一个叶子结点内(一般大小为一页)的各条数据记录按顺序存放,所以每当我们有一条新的记录插入时,Mysql会根据主键将其插入的其对应的位置,如果页面达到装载因子,则会开辟一个新的页。
使用自增主键的好处:
- 使用自增主键,每次插入新的记录时,就会顺序的插入到B+树中,当一页写满时,就会自动开辟新的一页。这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时不需要移动数据,因此效率很高,也不会增加很多开销在维护索引上。
- 当我们不使用自增主键时,每次插入都是随机的值,近似于每次插入都会移动数据。
Mysql不得不为了将新纪录插到合适的而移动数据,增加开销,频繁的移动分页操作导致造成了大量的碎片。得到了不够紧凑的索引结构,后续不得不通过 OPTIMIZE TABLE 来重建表并优化填充页面。
InnoDB 存储引擎采用了聚集(clustered)的方式,因此每张表的存储都是按主键的顺序进行存放。如果没有显式地在表定义时指定主键,InnoDB 存储引擎会为每一行生成一个 6 字节的 ROWID,并一次作为主键。
mysql 在频繁的更新、删除操作,会产生碎片。而含碎片比较大的表,查询效率会降低。此时需对表进行优化,这样才会使查询变得更有效率。
不用自增主键的场景
有没有什么场景适合用业务字段直接做主键的呢?还是有的。比如,有些业务的场景需求是这样的:只有一个索引;该索引必须是唯一索引。你一定看出来了,这就是典型的 KV 场景。由于没有其他索引,所以也就不用考虑其他索引的叶子节点大小的问题。这时候我们就要优先考虑上一段提到的“尽量使用主键查询”原则,直接将这个索引设置为主键,可以避免每次查询需要搜索两棵树。