牛骨文教育服务平台(让学习变的简单)
博文笔记

MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(500W单表)

创建时间:2018-10-13 投稿人: 浏览次数:258

原文链接https://blog.csdn.net/mchdba/article/details/52279523

一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了说服他,所以准备做一个详细的测试。

 

作为互联网公司,一定有用户表,而且用户表UC_USER基本会有百万记录,所以在这个表基础上准测试数据来进行测试。

 

     大概环境是:Centos6.5、MySQL5.6.12

 

 

1、准备表以及数据
UC_USER,自增ID为主键:

CREATE TABLE `UC_USER` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT "主键",
  `USER_NAME` varchar(100) DEFAULT NULL COMMENT "用户名",
  `USER_PWD` varchar(200) DEFAULT NULL COMMENT "密码",
  `BIRTHDAY` datetime DEFAULT NULL COMMENT "生日",
  `NAME` varchar(200) DEFAULT NULL COMMENT "姓名",
  `USER_ICON` varchar(500) DEFAULT NULL COMMENT "头像图片",
  `SEX` char(1) DEFAULT NULL COMMENT "性别, 1:男,2:女,3:保密",
  `NICKNAME` varchar(200) DEFAULT NULL COMMENT "昵称",
  `STAT` varchar(10) DEFAULT NULL COMMENT "用户状态,01:正常,02:冻结",
  `USER_MALL` bigint(20) DEFAULT NULL COMMENT "当前所属MALL",
  `LAST_LOGIN_DATE` datetime DEFAULT NULL COMMENT "最后登录时间",
  `LAST_LOGIN_IP` varchar(100) DEFAULT NULL COMMENT "最后登录IP",
  `SRC_OPEN_USER_ID` bigint(20) DEFAULT NULL COMMENT "来源的联合登录",
  `EMAIL` varchar(200) DEFAULT NULL COMMENT "邮箱",
  `MOBILE` varchar(50) DEFAULT NULL COMMENT "手机",
  `IS_DEL` char(1) DEFAULT "0" COMMENT "是否删除",
  `IS_EMAIL_CONFIRMED` char(1) DEFAULT "0" COMMENT "是否绑定邮箱",
  `IS_PHONE_CONFIRMED` char(1) DEFAULT "0" COMMENT "是否绑定手机",
  `CREATER` bigint(20) DEFAULT NULL COMMENT "创建人",
  `CREATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "注册时间",
  `UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "修改日期",
  `PWD_INTENSITY` char(1) DEFAULT NULL COMMENT "密码强度",
  `MOBILE_TGC` char(64) DEFAULT NULL COMMENT "手机登录标识",
  `MAC` char(64) DEFAULT NULL COMMENT "mac地址",
  `SOURCE` char(1) DEFAULT "0" COMMENT "1:WEB,2:IOS,3:ANDROID,4:WIFI,5:管理系统, 0:未知",
  `ACTIVATE` char(1) DEFAULT "1" COMMENT "激活,1:激活,0:未激活",
  `ACTIVATE_TYPE` char(1) DEFAULT "0" COMMENT "激活类型,0:自动,1:手动",
  PRIMARY KEY (`ID`),
  UNIQUE KEY `USER_NAME` (`USER_NAME`),
  KEY `MOBILE` (`MOBILE`),
  KEY `IDX_MOBILE_TGC` (`MOBILE_TGC`,`ID`),
  KEY `IDX_EMAIL` (`EMAIL`,`ID`),
  KEY `IDX_CREATE_DATE` (`CREATE_DATE`,`ID`),
  KEY `IDX_UPDATE_DATE` (`UPDATE_DATE`)
) ENGINE=InnoDB AUTO_INCREMENT=7122681 DEFAULT CHARSET=utf8 COMMENT="用户表"

 

 

 

UC_USER_PK_VARCHAR表,字符串ID为主键,采用uuid

CREATE TABLE `UC_USER_PK_VARCHAR_1` (
  `ID` varchar(36) CHARACTER SET utf8mb4 NOT NULL DEFAULT "0" COMMENT "主键",
  `USER_NAME` varchar(100) DEFAULT NULL COMMENT "用户名",
  `USER_PWD` varchar(200) DEFAULT NULL COMMENT "密码",
  `BIRTHDAY` datetime DEFAULT NULL COMMENT "生日",
  `NAME` varchar(200) DEFAULT NULL COMMENT "姓名",
  `USER_ICON` varchar(500) DEFAULT NULL COMMENT "头像图片",
  `SEX` char(1) DEFAULT NULL COMMENT "性别, 1:男,2:女,3:保密",
  `NICKNAME` varchar(200) DEFAULT NULL COMMENT "昵称",
  `STAT` varchar(10) DEFAULT NULL COMMENT "用户状态,01:正常,02:冻结",
  `USER_MALL` bigint(20) DEFAULT NULL COMMENT "当前所属MALL",
  `LAST_LOGIN_DATE` datetime DEFAULT NULL COMMENT "最后登录时间",
  `LAST_LOGIN_IP` varchar(100) DEFAULT NULL COMMENT "最后登录IP",
  `SRC_OPEN_USER_ID` bigint(20) DEFAULT NULL COMMENT "来源的联合登录",
  `EMAIL` varchar(200) DEFAULT NULL COMMENT "邮箱",
  `MOBILE` varchar(50) DEFAULT NULL COMMENT "手机",
  `IS_DEL` char(1) DEFAULT "0" COMMENT "是否删除",
  `IS_EMAIL_CONFIRMED` char(1) DEFAULT "0" COMMENT "是否绑定邮箱",
  `IS_PHONE_CONFIRMED` char(1) DEFAULT "0" COMMENT "是否绑定手机",
  `CREATER` bigint(20) DEFAULT NULL COMMENT "创建人",
  `CREATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "注册时间",
  `UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "修改日期",
  `PWD_INTENSITY` char(1) DEFAULT NULL COMMENT "密码强度",
  `MOBILE_TGC` char(64) DEFAULT NULL COMMENT "手机登录标识",
  `MAC` char(64) DEFAULT NULL COMMENT "mac地址",
  `SOURCE` char(1) DEFAULT "0" COMMENT "1:WEB,2:IOS,3:ANDROID,4:WIFI,5:管理系统, 0:未知",
  `ACTIVATE` char(1) DEFAULT "1" COMMENT "激活,1:激活,0:未激活",
  `ACTIVATE_TYPE` char(1) DEFAULT "0" COMMENT "激活类型,0:自动,1:手动",
  PRIMARY KEY (`ID`),
  UNIQUE KEY `USER_NAME` (`USER_NAME`),
  KEY `MOBILE` (`MOBILE`),
  KEY `IDX_MOBILE_TGC` (`MOBILE_TGC`,`ID`),
  KEY `IDX_EMAIL` (`EMAIL`,`ID`),
  KEY `IDX_CREATE_DATE` (`CREATE_DATE`,`ID`),
  KEY `IDX_UPDATE_DATE` (`UPDATE_DATE`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="用户表";

 

 

 

 

2、500W数据测试
2.1 录入500W数据,自增ID节省一半磁盘空间
确定两个表数据量

# 自增id为主键的表

mysql> select count(1) from UC_USER;

+----------+

| count(1) |

+----------+

|  5720112 |

+----------+

1 row in set (0.00 sec)

 

mysql>

 

# uuid为主键的表

mysql> select count(1) from UC_USER_PK_VARCHAR_1;                     

+----------+

| count(1) |

+----------+

|  5720112 |

+----------+

1 row in set (1.91 sec)

 

占据的空间容量来看,自增ID比UUID小一半左右。

3、总结
在500W记录表的测试下:

(1)      普通单条或者20条左右的记录检索,uuid为主键的相差不大几乎效率相同;

(2)      但是范围查询特别是上百成千条的记录查询,自增id的效率要大于uuid;

(3)      在范围查询做统计汇总的时候,自增id的效率要大于uuid;

(4)      在存储上面,自增id所占的存储空间是uuid的1/2;(int占4个字节,uuid占3个字节)

 
--------------------------------------------------------------------------------------------------------------------------

结论

(1)单实例或者单节点组:

经过500W、1000W的单机表测试,自增ID相对UUID来说,自增ID主键性能高于UUID,磁盘存储费用比UUID节省一半的钱。所以在单实例上或者单节点组上,使用自增ID作为首选主键。

(2)分布式架构场景:

20个节点组下的小型规模的分布式场景,为了快速实现部署,可以采用多花存储费用、牺牲部分性能而使用UUID主键快速部署;

20到200个节点组的中等规模的分布式场景,可以采用自增ID+步长的较快速方案。

200以上节点组的大数据下的分布式场景,可以借鉴类似twitter雪花算法构造的全局自增ID作为主键。

 

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。