首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server uniqueidentifier 與 NEWID():全域唯一識別碼完整指南

     編輯:關於SqlServer

基本特性

  • 儲存大小:16 位元組二進位值。
  • 顯示格式:`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` (36 字元含連字號)。
  • 生成方式:必須搭配 NEWID() 函數,**不支援** `IDENTITY` 自動遞增。
  • 唯一性來源:網卡 MAC 位址 + CPU 時鐘 + 隨機元件,理論上全域唯一 (GUID)。
  • 多欄位支援:單一資料表可定義多個 `uniqueidentifier` 欄位。

常見用法範例

1. 變數指派


DECLARE @MyId UNIQUEIDENTIFIER;
SET @MyId = NEWID();
PRINT 'Value: ' + CONVERT(VARCHAR(36), @MyId);
-- 輸出範例:6F9619FF-8B86-D011-B42D-00C04FC964FF

2. 建表預設值自動生成


CREATE TABLE Cust (
    CustomerId UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID(),
    Company VARCHAR(30) NOT NULL,
    ContactName VARCHAR(60) NOT NULL,
    -- 其他欄位...
);
INSERT INTO Cust (Company, ContactName, ...) VALUES ('Acme', 'John', ...); -- CustomerId 自動產生

3. 明確指定值 (罕見,僅遷移/測試用)


DECLARE @MyId UNIQUEIDENTIFIER;
SET @MyId = 'A972C577-DFB0-064E-1189-0154C99310DA'; -- 必須符合格式

效能與設計權衡:為什麼不建議作為叢集索引鍵?

缺點影響
值長 (16 bytes) vs INT (4 bytes)索引體積膨脹 4 倍,記憶體/快取效率降低,I/O 增加
隨機分佈 (NEWID 非循序)導致叢集索引嚴重分頁分裂、碎片化、寫入效能劇降
無序無意義難以除錯、人工記憶、排序無業務語意
不支援遞增依賴邏輯無法用 `>` 比較新舊記錄,破壞部分應用模式

改進方案:NEWSEQUENTIALID() (SQL 2005+)

  • 生成**循序 GUID**,大幅減少分頁分裂,適合作為叢集索引鍵。
  • 限制:只能作為欄位預設值 (`DEFAULT NEWSEQUENTIALID()`),不可在變數指派或臨時表中直接呼叫。
  • 安全性較低 (可推測下一值),不可用於需不可預測性的場景 (如公開 API Key)。

適用場景建議

  • ✅ **分散式系統主鍵** (多節點獨立寫入、合併無衝突)。
  • ✅ **公開暴露的識別碼** (URL、API Token、檔案名) 需不可猜測性。
  • ✅ **異構資料整合** (合併多來源資料無主鍵衝突)。
  • ❌ **單機高頻寫入主表叢集索引** → 改用 `BIGINT IDENTITY` 或 `NEWSEQUENTIALID()`。
  • ❌ **大量關聯查詢的外鍵欄位** → 索引體積過大,改用代理鍵。

總結

`uniqueidentifier` + `NEWID()` 提供全域唯一識別能力,是分散式、整合、公開識別碼的利器。但其隨機性與體積代價,使其**不適合**作為高頻單機核心交易表的叢集索引鍵。選型時必須在「全域唯一性需求」與「儲存/效能成本」間權衡,善用 `NEWSEQUENTIALID()` 緩解分頁分裂問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved