前言
這 21 條規範源自實戰踩坑總結,適用於 SQL Server 專案,大多數原則通用於關係資料庫。遵循它們,能避開 80% 的效能與維護陷阱。
21 條鐵律
- 精通工具箱:花一個周末瀏覽所有 T-SQL 命令與 SSMS 功能。需要時才查語法,但必須知道「有這個工具」。
- 拒絕游標:游標 = RBAR (Row-By-Agonizing-Row)。集合思維 (Set-based) 通常快 100~10000 倍。唯一例外:極複雜邏輯無法集合化,且資料量極小。
- 正規化優先:依 3NF/BCNF 設計。反正規化僅在證實效能瓶頸且經測試驗證後實施。過早反正規化常導致資料不一致與更慢。
- 禁止 SELECT *:明確列出欄位 → 減少 I/O/網路/記憶體、啟用覆蓋索引、防止結構變更破壞應用。
- 瞭解存取模式再建索引:讀多寫少 → 多索引;寫多讀少 → 精簡索引。每個索引皆有維護成本 (INSERT/UPDATE/DELETE/MERGE 皆需更新)。
- 低基數欄位別建索引:性別、布林、狀態碼 (少於 10 個相異值) → 索引選擇率極低,優化器傾向掃描。改用篩選索引或組合索引前導欄位。
- 長交易必須用顯式交易:
BEGIN TRAN ... COMMIT/ROLLBACK 保護一致性,縮短鎖定持有時間,避免死鎖擴大。
- 固定存取順序防死鎖:所有預存程序以相同順序鎖定表 (如 Parent → Child)。死鎖多源於順序不一。
- 拒絕大結果集回傳應用層:UI 無法承載 10 萬筆。實作分頁、搜尋、篩選,單次回傳 ≤ 200 筆。
- 用戶端游標優於伺服器端:ADO.NET
SqlDataReader (Firehose) 或離線 DataSet 減少伺服器資源佔用與鎖定時間。
- 參數化查詢 (Prepared Statement):防注入、啟用計畫重用、避免隱含轉換。永遠不要字串拼接 SQL。
- 開發環境用真實資料量:最少 10 萬筆核心表資料。小資料掩蓋缺失索引、鎖定爭用、統計資料偏差。
- 大量匯入用 BULK INSERT / bcp / SSIS:逐筆 INSERT 效能極差,記錄檔暴增。最小日誌模式下 BULK INSERT 可達 GB/秒。
- 設定合理 Command Timeout:預設 30 秒常不夠。依據實測 P99 執行時間設定,並實作重試/取消邏輯。
- 樂觀並發控制:資料表加
RowVersion (TIMESTAMP) 欄位,更新時 WHERE ID=@ID AND RowVer=@OldVer,失敗則重讀合併。
- 身分值取回用 SCOPE_IDENTITY():
@@IDENTITY 受觸發器影響回傳錯誤表的身分值;IDENT_CURRENT 有併發競爭。SCOPE_IDENTITY() 最安全。
- 能 NOT NULL 就 NOT NULL:NULL 額外儲存位圖、查詢需
IS NULL 判斷、三值邏輯易出錯。業務允許空值才用 NULL,否則給預設值。
- 慎用 TEXT/NTEXT/IMAGE:已淘汰,改用
VARCHAR(MAX) 等。LOB 儲存/查詢/索引皆有特殊限制與成本。
- 少用暫存表 (#temp):優先用 CTE、衍生表、表值變數、
APPLY。暫存表產生 tempdb 壓力、統計資料重編譯、連線池複用問題。
- 會讀執行計畫:SSMS Ctrl+M、
SET STATISTICS IO, TIME ON、Query Store。辨識 Scan、Lookup、Sort、參數嗅探、基數估計偏差。
- 宣告式參考完整性 (PK/FK/UNIQUE/CHECK):讓引擎保護資料品質,省去應用層防禦性程式碼,優化器也能利用約束推導更優計畫。
給團隊的落地建議
- 列入 Code Review 清單:違反第 2、4、10、15、20 條者必須重寫。
- 建立「索引請求單」流程:開發提交查詢與執行計畫,DBA 評估建立/調整索引。
- 每季進行「效能體檢」:Top 20 耗資源查詢、索引碎片、統計資料新鮮度、檔案成長趨勢。
結語
規範不是束縛,而是累積經驗後的自由。內化這 21 條,你的 SQL 將更健壯、更快速、更易維護。