跳到主要內容

← 返回部落格

UUID vs 自增 ID:資料庫主鍵該選哪個?

建表時你會選一種主鍵策略 —— 而這個決定的影響比想像中大。最常見的兩種是自增整數UUID。以下比較兩者,以及何時該用哪個。

自增整數

BIGINT AUTO_INCREMENT(Postgres 的 SERIAL)這種欄位,會隨著資料插入依序發出 1、2、3⋯⋯

優點:體積小(4–8 位元組)、人類可讀、天然有序,且索引局部性極佳 —— 新列附加到 B-tree 尾端,插入很快。

缺點:會洩漏資訊(對手看到 /users/5000 就知道你的規模)、可被猜測(授權若不嚴會導致列舉攻擊),而且在分散式或分片系統中很難用,因為兩個節點無法各自獨立產生下一個號碼而不協調。

UUID

UUID 是一組 128 位元識別碼,像 550e8400-e29b-41d4-a716-446655440000。v4 版本是隨機的,任何節點都能無需協調地產生,且碰撞機率趨近於零。你甚至能在送進資料庫前就在前端產生。用 UUID 產生器產生一批就能看到格式。

優點:無需協調即全域唯一、不洩漏數量、無法猜測、可跨資料庫合併。

缺點:較大(16 位元組,文字形式 36 字)、對人不友善,而且關鍵是 —— 隨機的 UUIDv4 會傷害索引局部性。因為新鍵隨機落在 B-tree 各處,插入會造成頁分裂、索引碎片化,在大表上拖慢寫入。

折衷方案:UUIDv7 / ULID

你不必在「到處唯一」與「索引友善」之間二選一。時間排序的 ID,像 UUIDv7ULID,前綴內嵌時間戳,因此既全域唯一大致有序 —— 恢復索引局部性,同時保有 UUID 的分散式友善性。對想要 UUID 好處又不想付出寫入代價的新系統,這越來越成為預設。

怎麼選

  • 小型、單一資料庫、內部 ID? 自增簡單又快。
  • 對外公開的 ID,或想隱藏規模? 用 UUID(或對外用 UUID、內部仍保留整數主鍵)。
  • 分散式、分片、或前端產生 ID? 用 UUID —— 為了索引效能最好用 UUIDv7/ULID
  • 絕不用連續 ID 當安全機制;無論鍵多好猜,授權都必須確實執行。

一句話結論

自增贏在簡單與原始索引效能;UUID 贏在唯一性、隱私與分散式。想兼得,就用時間排序的 UUIDv7/ULID。

現在就需要識別碼?免費的 UUID 產生器在你的瀏覽器產生 RFC 4122 v4 ID —— 可批次產生、一鍵複製。