跳到主要内容

数据库使用自增 ID 和 UUID 作为主键的区别

前言 在设计数据库表的时候,MySQL官方推荐不要使用uuid或者不重复不连续的雪花id(long型且id唯一,单机递增),而是腿甲使用自增id,推荐使用auto_increment。

自增id做主键 在设计数据库表时,自增id 通过auto_increment,id依次递增,一般来说插入的id为上一个id值加1。

使用自增id,如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含NULL值的唯一索引作为主键索引、如果也没有这样的值作为主键索引,则InnoDB会选择设置内置6字节长的ROWID作为隐含的聚集索引(ROWID随着航记录的写入设置逐渐递增) 记录本身存放在主索引(一颗B+tree)的叶子节点上。这就需要同一个叶子节点内(大小为一个内存页或者磁盘页)的各个记录按照主键顺序存放,每当一天记录插入时,MySQL会根据其主键将其插入当前适当的节点位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟为一个新的页 使用主键自增,每次插入一条新的记录,记录就会沿着当前索引节点的后续位置,当一页写满,就会开辟一个新的页 减少了叶分裂和碎片的产生 自增id主键可能不连续,造成不连续的情况可能有: 唯一主键冲突 事务回滚 insert…select语句批量申请自增id UUID做主键 UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分。其目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其它人冲突的UUID。在这样的情况下,就不需考虑数据库创建时的名称重复问题。目前最广泛应用的UUID,是微软公司的全局唯一标识符(GUID),而其他重要的应用,则有Linux ext2/ext3文件系统、LUKS加密分区、GNOME、KDE、Mac OS X等等。另外我们也可以在e2fsprogs包中的UUID库找到实现。

使用UUId做主键,可以减少主键ID冲突 使用UUID,生成的id不仅是独立的,而且库是独立的。对以后的数据库操作提供了极大地方便。 写入的目标页很可能已经刷新到磁盘上并从缓存上移除,或者还没有加载到缓存中,InnoDB在插入之前就不得不先找到并从磁盘中读取目标页到内存中,这将导致大量的随机IO操作 由于斜入式乱序的,InnoDB不得不频繁的做分页操作,以便为新的行分配空间,页分裂导致移动大量的数据,一次插入最少需要修改三个页以上 由于频繁的分页操作 ,页会变得稀疏并被不规则的填充,最终会导致数据有碎片。在把随机值(uuid和雪花id)载入到聚簇索引(innodb默认的索引类型)以后,有时候会需要做一次OPTIMEIZE TABLE来重建表并优化页的填充,这将又需要一定的时间消耗。 综上所述可得: 如果INnoDB表的数据写入顺序可以和B+树缩印的叶子节点顺序一致的话,此时存储效率最高。为了存储和查找性能应该使用自增ID作为主键 对于InnoDB的主键索引,数据会按照主键进行排序,由于UUID的无序性,InnoDB会产生大量的IO压力,此时不适合使用UUID作为物理主键,可以作为逻辑主键,物理主键仍未自增id。为了全局唯一性,应该使用UUID做索引关联其他表或做外键

参考