在设计关系型表结构时,设计主键是一个必不可少的步骤。而在实际应用中,经常会使用自增 id 作为主键。接下来分析一下自增主键和手动生成主键的区别。
自增主键
优点
- MySQL 推荐使用连续自增的主键 id,官方的推荐是 auto_increment
- Innodb 的索引特性使自增 id 做主键是效率最好,而且是增量增长,按顺序存放,对于检索非常有利
- 数字型,占用空间小,易排序
- 如果通过非系统增加记录时,可以不用指定该字段,不用担心主键重复问题
缺点
- 表的自增 id 达到上限后,再申请时它的值就不会改变,进而导致继续插入数据时报主键冲突的错误。
- row_id 达到上限后,则会归 0 再重新递增,如果出现相同的 row_id,后写的数据会覆盖之前的数据。
- 在手动要插入指定ID的记录时会比较麻烦
- 当多个系统需要数据导入时,很难保证原系统的ID不发生主键冲突,特别是在新系统上线时,新旧系统并行存在,并且是异库异构的数据库的情况下,需要双向同步时,自增主键将是个的噩梦。
- 若系统是数字型的,在导入时为了区分新老数据,可能想在老数据主键前统一加一个字符标识(例如“o”,old)来表示这是老数据,那么自动增长的数字型又面临一个挑战
- 主从复制:1)statement 模式下,由于他是记录的执行语句,所以,为了让这些语句在 slave 端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在 slave 端执行的时候能够得到和在 master 端执行时候相同的结果。在自增主键上面,有可能会出现不一致的情况。2)row 模式下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容
- 主主双向复制时主键自增长一定会出现重复,因为多主都可以对服务器有写权限
手动生成主键
最好保证插入顺序
优点
- 解决了自增上线问题
- 当异库异构的数据库的情况下,需要双向同步时,解决了自增主键噩梦的问题
- 插入数据时不需要再取出产生的 id 值
- 主从复制和主主双向复制的情况下可以有效保证重复问题
缺点
- 需要额外设计主键生成策略,还需要保证不会发生主键冲突问题
- 占用磁盘空间较大
- 通过非系统增加记录时,需要指定该字段,需要解决重复问题
- 当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突
- 如果与其他系统主键类型或长度不同时,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重,又一个噩梦的开始
结论
- 小型系统或者系统架构初期,数据没有超过百万或者千万,可以使用自增主键
- 当数据成长到几百万或者超过千万时,并且增量很高时,这时就涉及到分库分表,这时就必须使用手动生成id方案