在前一篇文章中,我談到了Snowflake IDs。它們很棒,但它們需要一些設定,因為你需要管理「Worker IDs」。
如果你想要一個更簡單的選擇,同時能提供相同的優勢——安全連結和快速數據庫排序——你應該看看ULIDs (Universally Unique Lexicographically Sortable Identifiers)。
為何不直接使用 UUID 呢?
大多數開發者從自增整數切換到 UUID 是因為他們想隱藏其商業量。如果你的訂單 ID 是 order/550e8400-e29b...,就沒人知道你是否有 1 個客戶或 100 萬個客戶。
但 UUID 有一個主要問題:它們是完全隨機的。
當你將百萬個隨機 UUID 插入資料庫時,「B-Tree」索引會變得碎片化且變慢。你的資料庫必須在硬碟上跳躍尋找新數據要放的位置。
ULIDs 可以解決這個問題。
一個 ULID 是 128 位元(就像一個 UUID),但 ID 的第一部分是一個時間戳。這意味著 ULIDs 是按時間順序排列的。它們像 UUID 那樣獨一無二,但排序方式像整數。
這裡是如何在四個簡單步驟中將 ULIDs 實現到您的 Rails 8 應用程式中。
步驟 1:安裝 Gem
我們將使用 ulid gem 來生成字串。將這個添加到您的 Gemfile 中:
gem "ulid"
在你的終端運行 bundle install。
第 2 步:ULID 的關注
我們希望將 ULIDs 輕鬆添加到任何模型中。這的最佳方法是一個 關注。這段代碼將確保每當我們創建一條新記錄時,都會生成並分配一個 ULID。
在 app/models/concerns/has_ulid.rb 裡創建一個新文件:
# app/models/concerns/has_ulid.rb
module HasUlid
extend ActiveSupport::Concern
included do
# Before we save to the DB, generate the ULID
before_create :set_ulid
end
private
def set_ulid
# ULID.generate creates a string like: 01ARZ3NDEKTSV4RRFFQ69G5FAV
self.id ||= ULID.generate
end
end
第 3 步:遷移
當你建立一個新模型時,你需要告訴 Rails 這個 id 是一個 string,而且你必須禁用預設的自動遞增邏輯.
rails g model Product name:string
開啟遷移檔案並像這樣修改:
# db/migrate/XXXXXXXXXXXXXX_create_products.rb
class CreateProducts < ActiveRecord::Migration[8.0]
def change
# id: false stops the automatic integer ID
create_table :products, id: false do |t|
# We use string for ULID primary key
t.string :id, primary_key: true
t.string :name
t.timestamps
end
end
end
第四步:更新模型
現在,只要包含我們在第二步中寫的內容。
# app/models/product.rb
class Product < ApplicationRecord
include HasUlid
end
第五步:觀察其運作
開啟您的 Rails 控制台 (bin/rails c) 並建立一些產品:
Product.create(name: "Laptop")
Product.create(name: "Monitor")
Product.create(name: "Keyboard")
# Check the IDs
Product.pluck(:id)
# => ["01HQV...", "01HQV...", "01HQV..."]
如果你仔細看,所有的ID都以相同的字元開頭,因為它們是在同一分鐘建立的。由於它們可以排序,你仍然可以運行 Product.order(:id),它們將會以正確的時間順序排列!
我為何喜歡 ULIDs for Rails
- 表現更佳: 由於 ID 可排序,PostgreSQL (或 SQLite) 可以將它們附加到索引的末尾。這對於「寫入密集型」應用程式比隨機 UUID 快得多。
- 易讀性: ULIDs 使用一個特殊字母表 (Crockford's Base32),排除了容易混淆的字母,如 "I"、"L" 和 "O"。這讓它們如果使用者必須輸入時,更易於閱讀。
- 無需設定: 與 Snowflake IDs 不同,你不需要設定伺服器 ID 或工作節點。你只需要安裝這個 gem 就可以了.
大概就是這樣。這是一個小型的架構變更,讓你的應用程式感覺更加專業和可擴展。












