Utilo

UUID v4 vs UUID v7 vs ULID:你應該使用哪個唯一ID?

對於資料庫金鑰,API和分散式系統,與效能,隱私和格式權衡進行隨機 UUID v4,時間順序 UUID v7 和 ULID 的比較。

· 5 分鐘閱讀

自動增加的整數幾十年來一直是預設的初級金鑰。它們是緊且快速的,但它們需要一箇中央資料庫來分配數字,洩露你有多少記錄,。全球獨一無二的識別符解決了這些問題:任何伺服器,移動應用程式或離線客戶端都可以建立一個永遠不會碰撞的ID。問題在於是哪種。本指南比較了2026年最流行的三個選項:UUID版本 4,UUID版本 7 和 ULID。

一個快速的更新 UUID

UUID (通用唯一識別符號) 是一個128位的值,通常用32個十六進位制數字寫成五組:

550e8400-e29b-41d4-a716-446655440000

目前的標準RFC 9562 (於2024年釋出,取代RFC 4122),定義了幾個版本。一些位符號編碼版本和變體;其餘取決於版本。第三組始於版本號,所以你可以一眼看出v4和v7。

UUID v4:完全隨機

一個版本4 UUID 包含 122 個隨機位加上 6 個版本和變體的固定位。

優勢

  • 每種語言和資料庫都有內建的函式,例如JavaScript中的crypto.randomUUID()或PostgreSQL中的gen_random_uuid()。
  • 沒有時間,沒有機器識別符號,沒有序列。
  • 碰撞的可能性是微不足道的。需要生成約2.7 × 10^18的ID,

弱點

  • 隨機順序會損害資料庫索引。在PostgreSQL,MySQL和SQL伺服器中使用的B樹索引,在新金鑰以不斷增加的順序到達時表現最好。隨機鍵會在索引中出現,導致頁面分裂,快取位置不好,。在大型表格中,插入吞吐量可能會顯著下降,索引會比必要的更大。
  • 不能按建立時間進行排序,所以需要一個單獨的 created_at 列來進行時間查詢。

UUID v7:時間順序

版本7將 48 位 Unix 時間放在前面的毫秒,其次是 74 位隨機性 (一些實現將其部分作為在同一毫秒內排序的計時器)。

01928c3e-5b7a-7c4d-9f3e-2a1b4c5d6e7f
└─timestamp─┘ └version 7

優勢

  • 新的ID大致增加,所以插入新增到索引的末尾像自動增量鍵。這使得索引緊,寫作快。
  • 按建立時間按ID排序排序,這使得基於游標的排列簡單:WHERE id > :last_id ORDER BY id LIMIT 50。
  • 它仍然是一個標準 UUID:它適合已經接受 UUID 的原生 uuid 列,ORM 和 API。
  • 你可以從ID中提取建立時間進行除錯。

弱點

  • 建立時間是任何看到ID的人都能看到的。對於大多數記錄來說,這是無害的;對於一些使用者來說,例如隱私敏感產品中的使用者帳戶,它可能會顯示某人何時註冊。
  • 需要一個相當精確的鐘。大量的時鐘跳向後可以產生比現有的ID更早排序的ID;好的圖書館使用單調計數器來處理這一問題。
  • 本源生成函式是較新的。PostgreSQL 18新增了 uuidv7();在舊版本中,生成應用程式程式碼。

ULID:可分類和緊的文字

ULID (普遍獨特的詞典解析識別器) 之前 UUID v7 使用相同的想法:48 位毫秒時間,其次是 80 個隨機位。區別在於文字形式:Crockford Base32的26個字元。

01J9Z3K8M2Q7X4V5B6N8P0R2T4

優勢

  • 短於36個字元的 UUID 字串和 URL 安全。
  • 字母大寫不敏感,不含含糊的字母 (I,L,O,U),因此更容易大聲閱讀或打字。
  • 詞典學字串排序等於時間排序,這有助於儲存ID作為文字的系統,例如關鍵值儲存或日誌檔名。

弱點

  • 它不是 UUID,因此它不適合沒有轉換的原生 UUID 列型別 (儘管其 128 位可以儲存在一箇中)。
  • 一個社群規範而不是IETF標準,圖書館之間的行為略有不同。
  • 像V7一樣,它暴露了創造時間。

一對一的比較

財產 其他 無線路標識號 標籤:
尺寸 128位 128位 128位
文字長度 36 36 26
時間排序 沒有 是的 是的
洩露建立時間 沒有 是的 (ms) 是的 (ms)
標準 其他型別 其他型別 歐盟規範
本機DB型別 uuid uuid 通常是文字或二進位制
適合索引的外掛 窮人 很好 很好

儲存技巧

無論你選擇什麼,儲存ID為16位元組,而不是文字。一個36個字串佔用空間的兩倍以上,。PostgreSQL具有原生 uuid 型別;MySQL 使用者可以使用 BINARY(16) 與 UUID_TO_BIN(uuid, 1),第二個引數重新排序 v1 時間對於 v7 使用預設排序,因為它已經排序時間。

在APIs中以其正規文字形式展示ID。客戶應該把它們視為不透明的字串,

安全考慮

這些身份證都不是秘密。不要把它們當作密碼重置令牌或會話識別符號,。一個v4 UUID有足夠的隨機性無法測量,但v7和ULID具有可預測的時間前,可減少有效的。對於秘密,使用加密生成器生成至少128個隨機位,並將它們視為密碼,理想情況下只儲存一個雜湊。

另外還要考慮列舉。順序整數可以讓任何人猜到/orders/1001,/orders/1002。隨機或時間順序的ID使得這不切實際,但它們不能取代每一個請求的授權檢查。

你應該選擇哪一種?

  • 新系統中的資料庫初級金鑰: UUID v7。您可以獲得分散式生成和良好的索引效能,
  • 公共識別符號,建立時間必須保持私密: UUID v4,或 v7 內鍵結合單獨的隨機公共識別符號。
  • 基於文字的儲存,檔名或ID,人們可以輸入: ULID,其較短,小寫不敏感的形式。
  • **現有系統在v4上出現效能問題:**對於新表,考慮v7;在一個列中混合版本在技術上很好,因為兩者都是有效的 UUID。

生成識別符號

對於快速任務種子資料,測試裝置,手動插入基於瀏覽器的UUID生成器可以使用crypto.getRandomValues同時生成高達1,000個v4,v7或ULID值。在應用程式程式碼中,使用您語言的標準庫或維護良好的包,並儘可能接近建立記錄的ID。

總結

雖然 UUID v4 是隨機和私有,。UUID v7 新增了一個時間前,使插入快速,ID 可分類,同時保持標準 UUID。ULID提供了相同的排序方式,。對於大多數新應用程式來說,UUID v7 是最佳預設;當定時必須隱藏時,達到v4,當人類或基於文字的系統處理ID時,ULID。

本頁內容由英文自動翻譯而來,如發現錯誤,歡迎告訴我們。

相關指南