Skip to content

結構健檢 ​

Metadata/Analysis 照一組規則檢查一張資料表,發現寫成指令碼裡的註解:

text
-- [SCHEMA-001][Warning] IX_Loan_3:INCLUDE 帶了 Remark nvarchar(max),索引會跟著資料長成與資料表同一個量級。

預設關閉,由「指令碼附上結構健檢的發現」開啟。

內建規則 ​

識別碼嚴重度抓什麼
SCHEMA-001WarningINCLUDE 帶了大型物件資料行
SCHEMA-002Warning索引鍵是另一個索引的前綴
SCHEMA-003Warning資料表沒有叢集索引(堆積)
SCHEMA-004Error資料表沒有主索引鍵
SCHEMA-005Warning同語意的資料行型別不一致
SCHEMA-006Warning列舉語意的資料行沒有 CHECK
SCHEMA-007Information名稱像外來鍵卻沒有外來鍵
SCHEMA-008Informationdatetime 建議改用 datetime2
SCHEMA-009Warningtext/ntext/image 建議改用 max 型別

三級嚴重度不是裝飾:把「建議改用 datetime2」與「這張表沒有主索引鍵」放在同一級, 使用者看第三次就會把整個健檢關掉。

SCHEMA-002 只比較啟用的非叢集 B-tree 索引;篩選範圍、鍵排序與 INCLUDE 覆蓋都相容才 提示評估整併,不建議直接刪除。完全相同的兩個索引只報一個;叢集資料行存放區不算堆積。 第四層尚在載入或已失敗時整個分析器不產生發現,避免把未知狀態當成缺索引或缺約束。

一條規則一個型別 ​

ISqlSchemaRule 的實作各自獨立,不是一個巨大的 switch。規則要能單獨關掉, 而「關得掉」是這個功能可以預設開啟的前提。新增一條只有兩個動作:寫一個類別、 加進 SqlSchemaAnalyzer.BuiltInRules,不必動到任何既有的程式碼。

SqlSchemaAnalyzer.ForRules(null) 是全開,傳空集合是「一條都不跑」—— 混為一談的話,使用者關掉最後一條規則會得到全部打開。

規則是延遲列舉的,所以例外會在 foreach 當中才冒出來,圍在分析器那一層才接得到。 接住之後那一條這一次的發現整組丟掉:使用者要的是那份指令碼,不是一則健檢 錯誤,而半份發現比沒有發現更難懂。

順序穩定不是為了好看:發現會寫進指令碼,而那份指令碼要進得了版本控制。 順序每次不同的話,兩份內容相同的指令碼會 diff 出一整片紅。

誤報是這個功能唯一的死法 ​

每一條規則都同時驗「抓得到該抓的」與「不抓不該抓的」。只驗前者的話, 一條「永遠回報有問題」的規則會全綠通過——而誤報正是使用者關掉整個健檢的原因。 已經處理掉的幾種:

  • 有唯一索引的資料行不是外來鍵。 一個 PublicId uniqueidentifier 以 Id 結尾,卻是這張表自己的候選鍵。主索引鍵之外,單一資料行的唯一索引與唯一條件 約束也算——漏掉這一半的話 SCHEMA-007 會在每一張表上誤報。
  • 型別大類不同的同後綴資料行不比。 LoanId int 與 PublicId uniqueidentifier 都以 Id 結尾,那個差異多半是刻意的:一個是流水號, 一個是對外的識別碼。SCHEMA-005 只在同一個大類裡比(varchar 對 nvarchar 值得報,int 對 uniqueidentifier 不值得)。
  • 沒有說明的資料行不判斷是不是列舉。 SCHEMA-006 認的是「小整數或單字元, 而且說明裡寫了 =」這個組合;沒有說明時報出來就是猜。
  • 一個資料行都查不到時什麼都不報。 那是「這一輪沒有資料」(權限被收回、 物件剛被卸除),不是這張表沒有主索引鍵。報出來的話每一次降級都會多出假的發現。
  • 主索引鍵與唯一索引不算多餘。 它們同時是條件約束,刪不掉也不該刪, 即使索引鍵確實是別的索引的前綴。

兩個開關不是重複 ​

跑不跑由 SqlScriptContext.Analyzer 決定(null 就不跑),寫不寫由 SqlScriptOptions.IncludeAnalyzerComments 決定。關掉輸出時連跑都不跑: 那一輪要掃過每一個資料行與每一個索引,而結果沒有人會看到。分成兩個是為了 將來的獨立結果面板——那時要跑健檢但不寫進指令碼。

發現排在各物件的第一個敘述之前,不是整份的最前面:多物件時每一張表的發現 要跟著自己那張表,否則一份三十張表的指令碼開頭會是一整頁分不出屬於誰的警告。 那一段不參與批次分隔,全是註解的東西後面接一個 GO 沒有意義。

以 Apache-2.0 授權條款發布 · 專為 SSMS 22 設計