逻辑主键:没有业务含义,比如自增主键

业务主键:有业务含义,比如person表用身份证号当主键

插入性能

用逻辑主键的情况下,插入的过程中需要定位到页再插入,效率上会比直接追加到最后一个数据页要低很多。

相比之下,辅助索引带来的多一次的IO的开销其实并不一定很大,因为一方面Innodb本身有缓存,除非全表的随机扫描,否则在大部分业务情况下,访问基本都是可以命中缓存的。另一方面一个自增有序的主键其实在很多业务场景中,比如分页,排序等都会利用的上。而且innodb表对于主键的回盘查询效率是很高的。

比较倾向于建一个自增的id做主键,再将有业务含义的主键字段添加唯一索引的约束。如果可以的话,跨表关联查询时使用自增的id做为表关联的条件,不过这种情况下要对要不要在关联的表中保存业务主键字段做个权衡。

插入性能依赖插入顺序(主键).因为插入数据时需要按照主键寻找相应的页再进行插入,如果数据页不在内存中所以需要进行加载.

主键在插入新行或更新时导致移动行的时候可能会造成页分裂的问题.

当行主键值必须插入到一个已满的内存页中时Innodb会将该页分裂成两个页面来容纳数据行.分裂操作会导致表占用更多的磁盘空间.

如果可以保证业务字段能够有序的插入可以放弃自增主键使用业务字段当做主键.

总结对比

1、Innodb引擎是索引组织表,所谓索引组织表就是数据的插入顺序是根据主键的顺序来的,如果设置业务ID为主键,没有办法保证业务ID自增的话,那么新数据的插入会引起行迁移,这就是为什么很多回答中提到自增主键会提升插入效率。

2、Innodb引起表中所有的二级索引(非主键)的key值记录的都是主键,所以尽量要求主键的字段类型简单,而业务开发一般会用char/varchar来设计业务ID,用varchar和int来设计主键,影响的不仅仅是主键的长度,该表上所有的索引都会变大。从SQL优化的角度来说,优化的本质是减少IO,而减少IO最直接的方法其实就是设计最简单的字段类型(包括索引)。

3、从运维DBA的角度来说,非自增主键,十几亿条记录的表,要分批操作时候的绝望吗?如果有自增主键,直接指定primary key操作,会大大简化后期维护操作。当然可以通过updatetime字段来操作,但是不一定所有的表都有自更新的时间戳字段啊,而且也不一定能保证时间戳有索引。

4、如果表只有几百条数据,也不会有什么分批操作的需求,这就跟要不要设计索引一样。当然考虑实际情况或者业务场景,这样的表不设主键或索引也是可以接受的,但是从开发规范来说,难道制定主键规范的时候只说大家根据实际需求来吗?

所以一般的开发规范中都会要求设计自增ID为主键

留言

2018-10-05