MySQL主键使用自增ID(int)还是UUID(varchar)

自增长id:故名思意,id随着数据增长而增长。
UUID:含义是通用唯一识别码 (Universally Unique Identifier),是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的

使用自增长ID做主键的优点:

1、很小的数据存储空间
2、性能最好,innodb的索引特性导致了自增id做主键是效率最好的
3、容易记忆

使用自增长做主键的缺点:

1、如果存在大量的数据,可能会超出自增长的取值范围
2、很难处理分布式存储的数据表,尤其是需要合并表的情况下
3、安全性低,因为自增id是有规律的,容易被非法获取数据

使用UUID做主键的优点:

1、它是独一无二的,出现重复的几率极低
2、适合大量数据中的插入和更新操作,尤其是在高并发和分布式环境下
3、跨服务器数据合并非常方便
4、安全性较高

使用UUID做主键的缺点:

1、存储空间大(16 byte),因此它将会占用更多的磁盘空间
2、会降低性能
3、很难记忆

如何选择ID策略

如何选择策略取决于具体项目的应用场景,根据项目数据量级和是否分布式部署可以有以下选择:
1、项目是单机版的,并且数据量比较大(百万级)时,用自增长的,此时最好能考虑下安全性,做些安全措施。
2、项目是单机版的,并且数据量没那么大,对速度和存储要求不高时,用UUID。
3、项目是分布式的,那么首选UUID,分布式一般对速度和存储要求不高。
4、项目是分布式的,并且数据量达到千万级别可更高时,对速度和存储有要求时,可以用自增长。

有没有可替代方案

  既然两种方案各有优略,那么有没有更优的解决方案呢?答案是确定的-推特的雪花算法(snowflake)。SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和工作机器ID作区分)
  其实大部分项目可以使用twitter的snowflake来生成主键,snowflake生成的主键就是介于自增长和UUID之间的一种主键(存储空间小、速度快、分布式、时间序列)。据说snowflake每秒能够产生26万个ID,最多可以部署在1024个节点上,研发团队可以将snowflake作为底层的数据库主键工具类供团队成员使用。

贴一张snowflake的算法图:
snowflake64bit.jpg

大概解读一下,主要由四部分组成:

  • 首位代表符号位。0 为正,1位负,而在生成的 ID 中, 要求基本都是正数, 所以首位基本是0.
  • 41位的时间戳。用来记录当前时间与标记时间twepoch的毫秒数的差值,JAVA 应用中是长度13的 Long 型时间戳, 一共41位。计算下来大可以使用69年(T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69。在这里设置twepoch=1485882061743L ,(时间为2017-01-01 01:01:01)。
  • 5位数据中心 ID, 及5位工作机器 ID。 这里可以解决分布式 标志性问题。支持2的10次方台机器。数据中心和工作机器 ID 取值均为(0~31)
  • 12位序列号。每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号(1L << 12)

这里也有一篇非常优秀的文章->:MySQL主键应该用UUID还是INT类型

下一篇文章记录下snowflake的Java实现。

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://maplefix.top/archives/uuid-or-increase-of-mysql