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

SQL Server 資料表主鍵設計:從複合主鍵到代理鍵的最佳實踐

     編輯:關於SqlServer

前言:資料庫邏輯設計的核心挑戰

資料庫邏輯設計是一個廣泛且深度的議題。本文專注於在 MS SQL Server 開發應用中,資料表主鍵設計常遇到的問題與解決方案。透過實務案例分析,探討如何從傳統的業務複合主鍵轉向代理鍵設計,以提升系統效能、簡化開發複雜度並解決分頁難題。

現狀與問題:業務複合主鍵的連鎖效應

典型主從表設計場景

以銷售系統為例,通常包含主表(銷售單)與明細表(商品明細)。主表以單據號為主鍵,明細表則將單據號與商品編碼組成聯合主鍵。當業務延伸至第三層(如不同價格策略),主鍵需包含單據號、商品號與價格類型,形成三層級的複合主鍵。

複合主鍵帶來的四大痛點

  • 資料冗餘儲存:隨著主從關係延伸,子表需重複儲存父表所有主鍵欄位,儲存空間呈指數級增長
  • SQL 複雜度飆升:多欄位 JOIN 條件導致查詢語句冗長,維護困難
  • 程式開發負擔加重:需傳遞多個參數進行關聯查詢,介面耦合度高
  • 查詢效能下降:資料庫需評估更多條件,複合索引體積大,WEB 分頁處理極其困難

解決方案:引入非業務代理鍵

核心設計原則

為解決上述問題,建議在存在主從關係的資料表中,額外新增一個非業務數值型欄位作為主鍵(代理鍵)。此欄位與業務邏輯無關,僅作為唯一識別碼。幾乎所有資料表皆可採用此設計模式。

為何不直接使用 IDENTITY 自增欄位?

雖然 SQL Server 的 IDENTITY 屬性可自動生成唯一值,但存在顯著限制:

  • 使用者無法干預數值,完全由資料庫控制
  • 發行訂閱複寫時處理麻煩
  • 部分資料還原時難以維護序列連續性
  • 插入資料後才能取得生成值,增加應用層複雜度

自製序列機制:參考 Oracle Sequence 設計

建立序列管理表 T_DB_SEQ,包含序列名稱、擁有者、當前值、最小/最大值、步長、循環標記等欄位。透過三個核心函數實現序列功能:

  1. F_create_SEQ(序列名):建立序列記錄
  2. F_GET_NEXT_SEQ_VAL(序列名):取得下一個值,保證並發一致性
  3. F_GET_SEQ_CUR_VAL(序列名):取得當前值

輔助函數包含設定值、刪除序列、判斷存在性等。主從表關聯時,子表使用自身序列值為主鍵,父表序列值為外鍵。

業務唯一性約束的替代方案

改用代理鍵後,原業務主鍵(如使用者登入帳號)失去 PRIMARY KEY 約束。解決方式有二:

  • 資料庫層:建立 UNIQUE CONSTRAINT 或 UNIQUE NONCLUSTERED INDEX
  • 應用層:寫入前檢查唯一性

索引策略:為何代理鍵採用非叢集索引?

代理鍵特性:無重複值、極少更新。SQL Server 單表僅能有一個叢集索引,這寶貴資源應留給高頻範圍查詢、排序分組的業務欄位。因此代理鍵主鍵建議使用 NONCLUSTERED 索引。

實戰應用:大數據量分頁查詢優化

B/S 架構下,大量資料分頁是效能關鍵。傳統前端分頁(全撈再切頁)在資料量大時會導致逾時。採用代理鍵設計配合儲存程序,在資料庫端完成分頁:

  1. 執行查詢 SQL 產生暫存表
  2. 暫存表新增 IDENTITY 識別欄位
  3. 依識別欄位計算頁碼範圍回傳
  4. 回傳總筆數供前端分頁控制

此方式大幅降低網路傳輸量與 Web 伺服器壓力,是大型系統分頁的標準解法。

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