查詢效能不佳的疑難排解:基數估計
SQL Server 的查詢最佳化工具是以成本為依據,這表示它會選取估計處理成本最低的查詢計劃來執行。查詢最佳化工具根據兩個主要因數來判斷執行查詢計劃的成本:
- 在查詢計劃的每一個層級進行處理的資料列總數,此稱為計劃的基數。
- 查詢中使用的運算子所指定的演算法成本模型。
第一個因數 (基數) 會作為第二個因數 (成本模型) 的輸入參數。因此,如果改善基數,便能產生更好的估計成本,進而可有更快的執行計劃。
SQL Server 主要是從建立索引或統計資料時所建立的長條圖 (透過手動或自動方式),來估計基數。有時候,SQL Server 也會使用條件約束資訊以及查詢的邏輯重寫來判斷基數。
在下列情況中,SQL Server 無法精確地計算基數。這會導致不精確的成本計算,使得產生並非最佳的查詢計劃。避免在查詢中使用這些建構可以提升查詢效能。有時也可以使用替代的查詢公式或其他方法,這些項目稍後也會提及。
- 查詢的述詞,在相同資料表的不同資料行之間使用比較運算子。
- 查詢的述詞使用運算子,且下列任一情況為真:
- 運算子任一邊所關聯的資料行中,沒有任何統計資料。
- 統計資料中的值分佈並不平均,但查詢會搜尋具有高度選擇性的值集。如果運算子不是等號 (=) 運算子,此情況會特別明顯。
- 述詞使用不等於 (!=) 比較運算子或 NOT 邏輯運算子。
- 查詢使用任一個 SQL Server 內建函數,或純量值的使用者自訂函數 (其引數不是常數值)。
- 查詢透過算術或字串串連運算子,與聯結資料行相關聯。
- 查詢所比較的變數,在編譯及最佳化查詢時其值不明。
下列方法可用來嘗試提升這些查詢類型的效能:
如果查詢使用比較或算術運算子來比較或結合兩個以上的資料行時,請考慮使用計算資料行並重寫查詢。例如,下列查詢會比較兩個資料行中的值:
SELECT * FROM MyTable WHERE MyTable.Col1 > MyTable.Col2
如果將計算資料行 Col3 加入 MyTable,用來計算 Col1 與 Col2 的差 (Col1 減 Col2),可以提升效能。接著,重寫查詢:
SELECT * FROM MyTable WHERE Col3 > 0
如果您在 MyTable.Col3 上建立索引,可能還可以更進一步提升效能。