自增長id/UUID/雪花算法的深層次分析比較


說到id之前,先說一下mysql數據庫的Innodb的主鍵索引,因為這和索引息息相關。

我們知道,在Innodb中,采用的是B+數索引。Innodb的存儲結構,是聚簇索引。對於聚簇索引,

(1)順序主鍵和隨機主鍵的對效率的影響很大。我們分插入和查詢來講:

         插入。在磁盤中,有一個頁的概念,而一頁的容量是固定的,每一頁按順序存儲數據,一般數據量達到一頁的15/16,則開始存到下一頁。但如果主鍵是隨機的,那么每次插入之前,為了找到它的位置,首先需要進行一次比較,找到它的合適位置,再進行插入。如果是在頁尾,那自然是最理想的效果。

     

UUID和自增長在程序中怎么實現此處不講,我們直接從性能和實際使用來分析。

     說到性能,就不等不提到索引,此處以InnoDB的BTree索引來講。

      uuid類型是varchar(36),而自增長Id則一般是bigInt類型。

      首先,大家要知道,id作為唯一索引,並不總是能提高效率。對於非常小的表,大部分情況下簡單的全表掃描效率更高,對於中大型的表,索引才非常有效。因為索引幫助存儲快速查找到記錄的同時,也會帶來額外的消耗。

       那么索引會帶來哪些額外的消耗呢?空間和時間。

下面做了一個實驗,在一個有足夠內存容納索引的服務器上插入100萬條記錄和300百萬條記錄,時間和空間上的消耗如下:

 

 根據上面的結果,索引是會消耗額外的物理空間的,而聚簇索引消耗的物理空間更大。當數據特別多的時候,相對於bigInt類型的自增長Id,varchar(36)類型的uuid消耗的物理空間更為明顯。

        在時間上,1)uuid由於占用的內存更大,所以查詢、排序速度會相對較慢;2)在存儲過程中,自增長id由於主鍵的值是順序的,所以InnoDB把每一條記錄都存儲在上一條記錄的后面。當達到頁的最大填充因子時(innodb默認的最大填充因子為頁大小的15/16,留出部分空間用於以后修改),下一條記錄就會寫入新的頁面中。一旦數據按照這種方式加載,主鍵頁就會被順序的記錄填滿。而對於uuid,由於后面的值不一定比前面的值大,所以InnoDB並不能總是把新行插入的索引的后面,而是需要為新行尋找合適的位置(通常在已有行之間),並分配空間,這會增加額外的很多工作。這也是為什么當索引的列過長的時候,需要采用前綴索引,或者哈希索引了。

        盡管自增長id的優點這么多,但實際大型項目中卻很少采用自增長id的,這是為什么呢?uuid幾乎保證了不同數據庫的不同表的id唯一,可以進行數據切分合並,而自增長id只能保證一個數據庫中的一張表的id唯一,進行數據庫合並的話並然會因主鍵沖突而失敗,這是一個硬傷。
————————————————
版權聲明:本文為CSDN博主「凌晨寫博客」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/hj12312/article/details/79715632


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM