不同數據量下主鍵類型的選擇

背景

之前面試的時候,有幾家公司都問了UUID,自增ID的優點以及缺點,個人當時只考慮到了索引方面(增刪查改的效率),沒有考慮到分佈式情況下的問題。

如果未來可能對數據進行合併、轉移,自增ID勢必會發生主鍵重複問題。

跨步自增可以解決分佈式問題,但是需要對充分考慮好跨域的步數。

UUID可以解決分佈式問題,但是因爲是varchar類型並且又很長,影響索引重組速度,又會大大影響增刪改效率(隨數據量變大到百萬千萬級時會慢慢接近自增ID)。

雪花算法可以得出一個int類型的ID,此ID可以直接進行排序,可以解決分佈式問題,但是生成時需要注意機器ID等參數,因爲生成的int值很大,在小項目運用時也會影響主鍵索引重組。

總之,根據當前數據量大小,再預測未來的數據量,然後選擇最合適的主鍵類型,像人員信息表這類數據,做大之後未來就極有可能會涉及分佈式和合表問題。

另外,如果說有一種情況,某表內的數據一開始在某個系統裏以自增爲主鍵的時候,插入時順便也生成一個UUID存放到一個臨時字段裏,數據轉移時將此表內的數據和結構先克隆爲另外一個新表,然後把新表的自增ID刪除,將UUID那個字段設置成主鍵後再合併到新系統的表中,這樣是不是即不影響之前的系統效率,也防止了分佈式主鍵衝突的問題?


測試部分:

 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小一半左右。

主鍵類型

數據文件大小

佔據容量 

自增ID

-rw-rw---- 1 mysql mysql 4.2G Aug 20 23:08 UC_USER_1.ibd

4.2 G

UUID

-rw-rw---- 1 mysql mysql 8.8G Aug 20 18:20 UC_USER_PK_VARCHAR_1.ibd

8.8 G

4.2 單個數據走索引查詢,自增id和 uuid效率比是:(2~3):1

主鍵類型

SQL語句

執行時間 (秒)

 

單條記錄查詢

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`MOBILE` ='14782121512';

0.069

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` ='14782121512';

0.274

 

小範圍查詢

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`MOBILE` IN( '14782121512','13761460105');

0.050

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` IN('14782121512','13761460105');

0.151

 

根據日期查詢

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:36' ;

0.269

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE`='2013-11-24 10:26:43' ;

0.810

 

4.3 範圍like查詢,自增ID性能優於UUID,比值(1.5~2):1

主鍵類型

SQL語句

執行時間 (秒)

 

(1)模糊範圍查詢1000條數據,自增ID性能要好於UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000;

2.398

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`MOBILE` LIKE '147%' LIMIT 1000;

5.872

 

(2)日期範圍查詢20條數據,自增ID稍微弱於UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20;

0.765

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-08-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 20;

1.090

 

(3)範圍查詢200條數據,自增ID性能要好於UUID

自增ID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 200;

1.569

UUID

SELECT SQL_NO_CACHE t.* FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36' ORDER BY t.`UPDATE_DATE` DESC LIMIT 200;

2.597

 

範圍查詢總數量,自增ID要好於UUID

自增ID

SELECT SQL_NO_CACHE COUNT(1) FROM test.`UC_USER_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36'  ;

1.129

UUID

SELECT SQL_NO_CACHE COUNT(1) FROM test.`UC_USER_PK_VARCHAR_1` t WHERE t.`CREATE_DATE` > '2016-07-01 10:26:36'  ;

2.302

 

4.4 寫入測試,自增ID比UUID效率高,比值(3~10):1

主鍵類型

SQL語句

執行時間 (秒)

 

 

修改一天的記錄

自增ID

UPDATE test.`UC_USER_1` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016-05-04 00:00:00'  ;

2.685

UUID

UPDATE test.`UC_USER_PK_VARCHAR_1` t SET t.`MOBILE_TGC`='T2' WHERE t.`CREATE_DATE` > '2016-05-03 10:26:36' AND t.`CREATE_DATE` <'2016-05-04 00:00:00'  ;

26.521

 

錄入數據

自增ID

INSERT INTO test.`UC_USER_1`(   ID,   `USER_NAME`,   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`,   `MOBILE`,   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` ) SELECT       NULL,    CONCAT('110',`USER_NAME`,8),   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`, CONCAT('110',TRIM(`MOBILE`)),   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100;

0.534

UUID

INSERT INTO test.`UC_USER_PK_VARCHAR_1`(    ID,   `USER_NAME`,   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`,   `MOBILE`,   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` ) SELECT         UUID(),   CONCAT('110',`USER_NAME`,8),   `USER_PWD`,   `BIRTHDAY`,   `NAME`,   `USER_ICON`,   `SEX`,   `NICKNAME`,   `STAT`,   `USER_MALL`,   `LAST_LOGIN_DATE`,   `LAST_LOGIN_IP`,   `SRC_OPEN_USER_ID`,   `EMAIL`, CONCAT('110',TRIM(`MOBILE`)),   `IS_DEL`,   `IS_EMAIL_CONFIRMED`,   `IS_PHONE_CONFIRMED`,   `CREATER`,   `CREATE_DATE`,   `UPDATE_DATE`,   `PWD_INTENSITY`,   `MOBILE_TGC`,   `MAC`,   `SOURCE`,   `ACTIVATE`,   `ACTIVATE_TYPE` FROM `test`.`UC_USER_1` LIMIT 100;

1.716

 

4.5、備份和恢復,自增ID性能優於UUID

主鍵類型

SQL語句

執行時間 (秒)

 

Mysqldump備份

自增ID

time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_1> UC_USER_1.sql

0m50.548s

UUID

time mysqldump -utim -ptimgood -h192.168.121.63 test UC_USER_PK_VARCHAR_1> UC_USER_PK_VARCHAR_1.sql

0m58.590s

 

MySQL恢復

自增ID

time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_1.sql

17m30.822s

UUID

time mysql -utim -ptimgood -h192.168.121.63 test < UC_USER_PK_VARCHAR_1.sql

23m6.360s

 

 

 

 

5、1000W總結

在1000W記錄表的測試下:

(1)普通單條或者20條左右的記錄檢索,自增主鍵效率是uuid主鍵的2到3倍;

(2)但是範圍查詢特別是上百成千條的記錄查詢,自增id的效率要大於uuid;

(3)在範圍查詢做統計彙總的時候,自增id主鍵的效率是uuid主鍵1.5到2倍;

(4)在存儲上面,自增id所佔的存儲空間是uuid的1/2;

(5)在寫入上面,自增ID主鍵的效率是UUID主鍵的3到10倍,相差比較明顯,特別是update小範圍之內的數據上面。

(6)在備份恢復上,自增ID主鍵稍微優於UUID。

 

6、MySQL分佈式架構的取捨

分佈式架構,意味着需要多個實例中保持一個表的主鍵的唯一性。這個時候普通的單表自增ID主鍵就不太合適,因爲多個mysql實例上會遇到主鍵全局唯一性問題。

 

6.1、自增ID主鍵+步長,適合中等規模的分佈式場景

          在每個集羣節點組的master上面,設置(auto_increment_increment),讓目前每個集羣的起始點錯開 1,步長選擇大於將來基本不可能達到的切分集羣數,達到將 ID 相對分段的效果來滿足全局唯一的效果。

 優點是:實現簡單,後期維護簡單,對應用透明。

 缺點是:第一次設置相對較爲複雜,因爲要針對未來業務的發展而計算好足夠的步長;

 規劃:

比如計劃總共N個節點組,那麼第i個節點組的my.cnf的配置爲:

auto_increment_offset  i

auto_increment_increment  N

 假如規劃48個節點組,N爲48,現在配置第8個節點組,這個i爲8,第8個節點組的my.cnf裏面的配置爲:

auto_increment_offset  8

auto_increment_increment  48

 

6.2、UUID,適合小規模的分佈式環境

         對於InnoDB這種聚集主鍵類型的引擎來說,數據會按照主鍵進行排序,由於UUID的無序性,InnoDB會產生巨大的IO壓力,而且由於索引和數據存儲在一起,字符串做主鍵會造成存儲空間增大一倍。

 在存儲和檢索的時候,innodb會對主鍵進行物理排序,這對auto_increment_int是個好消息,因爲後一次插入的主鍵位置總是在最後。但是對uuid來說,這卻是個壞消息,因爲uuid是雜亂無章的,每次插入的主鍵位置是不確定的,可能在開頭,也可能在中間,在進行主鍵物理排序的時候,勢必會造成大量的 IO操作影響效率,在數據量不停增長的時候,特別是數據量上了千萬記錄的時候,讀寫性能下降的非常厲害。

 優點:搭建比較簡單,不需要爲主鍵唯一性的處理。

缺點:佔用兩倍的存儲空間(在雲上光存儲一塊就要多花2倍的錢),後期讀寫性能下降厲害。

 

6.3、雪花算法自造全局自增ID,適合大數據環境的分佈式場景

由twitter公佈的開源的分佈式id算法snowflake(Java版本)

 IdWorker.java: 

package com.demo.elk;

import org.slf4j.Logger; 

import org.slf4j.LoggerFactory;

 

public class IdWorker {

   

    protected static final Logger LOG = LoggerFactory.getLogger(IdWorker.class);

    

    private long workerId;

    private long datacenterId;

    private long sequence = 0L;

 

    private long twepoch = 1288834974657L;

 

    private long workerIdBits = 5L;

    private long datacenterIdBits = 5L;

    private long maxWorkerId = -1L ^ (-1L << workerIdBits);

    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

    private long sequenceBits = 12L;

 

    private long workerIdShift = sequenceBits;

    private long datacenterIdShift = sequenceBits + workerIdBits;

    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    private long sequenceMask = -1L ^ (-1L << sequenceBits);

 

    private long lastTimestamp = -1L;

 

    public IdWorker(long workerId, long datacenterId) {

        // sanity check for workerId

        if (workerId > maxWorkerId || workerId < 0) {

            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));

        }

        if (datacenterId > maxDatacenterId || datacenterId < 0) {

            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));

        }

        this.workerId = workerId;

        this.datacenterId = datacenterId;

        LOG.info(String.format("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId));

    }

 

    public synchronized long nextId() {

        long timestamp = timeGen();

 

        if (timestamp < lastTimestamp) {

            LOG.error(String.format("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp));

            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));

        }

 

        if (lastTimestamp == timestamp) {

            sequence = (sequence + 1) & sequenceMask;

            if (sequence == 0) {

                timestamp = tilNextMillis(lastTimestamp);

            }

        } else {

            sequence = 0L;

        }

 

        lastTimestamp = timestamp;

 

        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;

    }

 

    protected long tilNextMillis(long lastTimestamp) {

        long timestamp = timeGen();

        while (timestamp <= lastTimestamp) {

            timestamp = timeGen();

        }

        return timestamp;

    }

 

    protected long timeGen() {

        return System.currentTimeMillis();

    }

}

測試生成ID的測試類,IdWorkerTest.java:

package com.demo.elk;

 

import java.util.HashSet;

import java.util.Set;

 

public class IdWorkerTest {

          

    static class IdWorkThread implements Runnable {

        private Set<Long> set;

        private IdWorker idWorker;

 

        public IdWorkThread(Set<Long> set, IdWorker idWorker) {

            this.set = set;

            this.idWorker = idWorker;

        }

 

        public void run() {

            while (true) {

                long id = idWorker.nextId();

                System.out.println("            real id:" + id);

                if (!set.add(id)) {

                    System.out.println("duplicate:" + id);

                }

            }

        }

    }

 

    public static void main(String[] args) {

        Set<Long> set = new HashSet<Long>();

        final IdWorker idWorker1 = new IdWorker(0, 0);

        final IdWorker idWorker2 = new IdWorker(1, 0);

        Thread t1 = new Thread(new IdWorkThread(set, idWorker1));

        Thread t2 = new Thread(new IdWorkThread(set, idWorker2));

        t1.setDaemon(true);

        t2.setDaemon(true);

        t1.start();

        t2.start();

        try {

            Thread.sleep(30000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

 

7,總結

(1)單實例或者單節點組:

經過500W、1000W的單機表測試,自增ID相對UUID來說,自增ID主鍵性能高於UUID,磁盤存儲費用比UUID節省一半的錢。所以在單實例上或者單節點組上,使用自增ID作爲首選主鍵。

 (2)分佈式架構場景:

         20個節點組下的小型規模的分佈式場景,爲了快速實現部署,可以採用多花存儲費用、犧牲部分性能而使用UUID主鍵快速部署;

          20到200個節點組的中等規模的分佈式場景,可以採用自增ID+步長的較快速方案。

          200以上節點組的大數據下的分佈式場景,可以借鑑類似twitter雪花算法構造的全局自增ID作爲主鍵。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章