1. 程式人生 > >MySQL 使用自增ID主鍵和UUID 作為主鍵的優劣比較詳細過程(500W單表)

MySQL 使用自增ID主鍵和UUID 作為主鍵的優劣比較詳細過程(500W單表)

一個開發同事做了一個框架,裡面主鍵是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作為主鍵。