共用方式為


從 SQL Server 2012 或更早版本升級至 2014 或更新版本的查詢效能降低

將 SQL Server 從 2012 或舊版升級至 2014 或更新版本之後,可能會遇到下列問題:大部分的原始查詢執行良好,但其中一些查詢的執行速度比舊版慢。 雖然有許多可能的原因和貢獻因素,但升級後基數估計(CE)模型的變化是比較常見的原因。 從 SQL Server 2014 開始,CE 模型已導入重大變更。

本文提供使用預設 CE 時所發生的查詢效能問題的疑難解答步驟和解決方案,但在使用舊版 CE 時不會發生。

注意

如果升級之後所有查詢的執行速度較慢,本文中導入的疑難解答步驟可能不適用於您的情況。

疑難解答:找出 CE 變更是否為問題,並找出原因

步驟 1:識別是否使用預設 CE

  1. 選擇升級后執行速度較慢的查詢。
  2. 執行查詢並 收集執行計劃
  3. 從執行計劃 屬性視窗,檢查 CardinalityEstimationModelVersion從執行計劃 屬性視窗 尋找 CE 模型版本。
  4. 值為 70 表示舊版 CE,而值為 120 或更高版本則表示使用預設 CE。

如果使用舊版CE,CE變更不是效能問題的原因。 如果使用預設 CE,請移至下一個步驟。

步驟 2:識別查詢優化器是否可以使用舊版 CE 產生更好的計劃

使用舊版 CE 執行查詢。 如果執行效能優於使用預設 CE,請移至下一個步驟。 如果效能未改善,CE 變更不是原因。

步驟 3:了解查詢為何使用舊版 CE 執行得更好

測試查詢的各種 CE 相關 查詢提示 。 針對 SQL Server 2014,請使用對應的追蹤旗標 413794724139 來測試查詢。 根據這些測試判斷哪些提示或追蹤旗標會對效能產生正面影響。

解決方法

若要解決此問題,請嘗試下列其中一個方法:

  • 優化查詢。

    可以理解的是,不一定可以重寫查詢,但特別是只有少數可以重寫的查詢時,此方法應該是第一選擇。 無論 CE 版本為何,以最佳方式撰寫的查詢都會執行得更好。

  • 使用步驟 3 中所識別的查詢提示。

    此目標方法可讓其他工作負載受益於預設 CE 假設和改進。 此外,這是比建立計劃指南更健全的選項。 它不需要 查詢存放區(QDS),不像強迫計劃(最健全的選擇)。

  • 強制制定好計劃。

    這是一個有利的選項,可用來以特定查詢為目標。 您可以使用計劃指南或 QDS 來強制執行計劃。 QDS 通常更容易使用。

  • 使用 資料庫範圍的組態 來強制使用舊版CE。

    這是較不慣用的方法,因為它是全資料庫設定,並套用至此資料庫的所有查詢。 不過,當目標方法不可行時,有時是必要的。 實作最簡單的選項肯定是最簡單的選項。

  • 使用追蹤旗標 9841 強制全球舊版 CE。 若要這樣做,請使用 DBCC TRACEON 或將追蹤旗標設定為 啟動參數

    這是最不具目標的方法,只有在您無法套用任何其他選項時,才應該做為暫時緩和措施。

啟用舊版 CE 的選項

查詢層級:使用查詢提示或 QUERYTRACEON 選項

  • 針對 SQL Server 2016 SP1 和更新版本,請使用提示 FORCE_LEGACY_CARDINALITY_ESTIMATION 進行查詢,例如:

    SELECT * FROM Table1
    WHERE Col1 = 10
    OPTION (USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION'));
    
  • 啟用追蹤旗標 9481 以強制使用舊版 CE 方案。 以下是範例:

    SELECT * FROM Table1
    WHERE Col1 = 10
    OPTION (QUERYTRACEON 9481)
    

資料庫層級:設定範圍組態或相容性層級

  • 針對 SQL Server 2016 和更新版本,請改變資料庫範圍設定:

      --Force a specific database to use legacy CE
      ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = ON;
    
      -- Validate what databases use legacy CE
      SELECT name, value
          FROM sys.database_scoped_configurations 
      WHERE name = 'LEGACY_CARDINALITY_ESTIMATION';
    
  • 改變資料庫的相容性層級。 這是 SQL Server 2014 唯一可用的資料庫層級選項。 請注意,這項變更只會影響CE。 若要判斷相容性層級變更的影響,請移至 ALTER DATABASE 相容性層級 (Transact-SQL) 並檢查其中的「差異」數據表。

    ALTER DATABASE <YourDatabase>
    SET COMPATIBILITY_LEVEL = 110  -- set it to SQL Server 2012 level
    

注意

除非使用覆寫追蹤旗標或查詢提示,否則這項變更會影響在變更組態之資料庫內容內執行的所有查詢。 由於預設 CE 而效能較佳的查詢可能會回歸。

伺服器層級:使用追蹤旗標

使用追蹤旗標 9481 強制全伺服器舊版 CE:

--Turn on 
DBCC TRACEON(9481, -1)
--Validate
DBCC TRACESTATUS

注意

除非使用覆寫追蹤旗標或查詢提示,否則這項變更會影響在 SQL Server 實例內容內執行的所有查詢。 由於預設 CE 而效能較佳的查詢可能會回歸。

常見問題集

針對在較低相容性層級執行的預先存在資料庫,建議的工作流程會將查詢處理器升級至較高的相容性層級,詳述於變更資料庫相容性模式和使用 查詢存放區 和使用案例 查詢存放區。 本文中介紹的方法適用於將 SQL Server 和 Azure SQL 資料庫 移至 130 或更新版本。

問 2:我沒有時間測試 CE 變更。 在此情況下,我該怎麼做?

對於預先存在的應用程式和工作負載,我們不建議移至預設CE,直到執行足夠的回歸測試為止。 如果您仍然有疑問,建議您仍升級 SQL Server 並移至最新的可用相容性層級。 作為預防措施,也啟用 SQL Server 2014 的追蹤旗標 9481,或為 SQL Server 2016 和更新版本設定LEGACY_CARDINALITY_ESTIMATION資料庫範圍ON設定,直到您有機會進行測試為止。

問 3:使用舊版 CE 是否有任何缺點?

未來的基數估計工具相關改善和修正以較新版本為中心。 版本 70 是可接受的中繼狀態。 不過,經過仔細測試之後,我們建議最終移至較新的 CE 版本,以受益於最新的 CE 修正。 從舊版 CE 移動時,查詢計劃變更的可能性很高,因此在變更生產系統之前先進行測試。 這些變更在許多情況下可以改善查詢效能,但在某些情況下,查詢效能可能會降低。

重要

默認 CE 是主要程式代碼路徑,將在未來進行長期投資和更深入的測試涵蓋範圍,因此請勿無限期地規劃使用舊版 CE。

問 4:我有數千個資料庫,而且不想針對每個資料庫手動開啟LEGACY_CARDINALITY_ESTIMATION。 是否有替代方法?

針對 SQL Server 2014,請啟用追蹤旗標 9481,以針對所有資料庫使用舊版 CE,而不論相容性層級為何。 針對 SQL Server 2016 和更新版本,請執行下列查詢逐一查看資料庫。 即使在另一部伺服器中還原或附加資料庫時,也會啟用此設定。

SELECT [name], 0 AS [isdone]
INTO #tmpDatabases
FROM master.sys.databases WITH (NOLOCK)
WHERE database_id > 4 AND source_database_id IS NULL AND is_read_only = 0

DECLARE @dbname sysname, @sqlcmd NVARCHAR(500);

WHILE (SELECT COUNT([name]) FROM #tmpDatabases WHERE isdone = 0) > 0
BEGIN
    SELECT TOP 1 @dbname = [name] FROM #tmpDatabases WHERE isdone = 0

    SET @sqlcmd = 'USE ' + QUOTENAME(@dbname) + '; 
        IF (SELECT [value] FROM sys.database_scoped_configurations WHERE [name] = ''LEGACY_CARDINALITY_ESTIMATION'') = 0
        ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = ON;'
 
    BEGIN TRY
        EXECUTE sp_executesql @sqlcmd
    END TRY
    BEGIN CATCH
        SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity,
            ERROR_STATE() AS ErrorState, ERROR_MESSAGE() AS ErrorMessage;
    END CATCH

    UPDATE #tmpDatabases
    SET isdone = 1
    WHERE [name] = @dbname
END;

針對 Azure SQL 資料庫,您可以建立支援票證,以在訂用帳戶層級啟用此追蹤旗標,但無法啟用伺服器層級。

問 5:使用舊版 CE 執行是否會防止我存取新功能?

即使啟用LEGACY_CARDINALITY_ESTIMATION,您仍然可以存取 SQL Server 版本和相關聯的資料庫相容性層級隨附的最新功能。 例如,在 SQL Server 2017 上啟用資料庫相容性層級 140 執行LEGACY_CARDINALITY_ESTIMATION的資料庫仍然可以受益於 調適型查詢處理 功能系列。

問 6:舊版 CE 何時會退出支援?

我們目前沒有計劃停止支援舊版CE。 不過,未來的基數估計工具相關改進和修正以較新版本的 CE 為中心。

問 7:我只有一些查詢會隨著預設 CE 回歸,但大部分的查詢效能都相同,甚至改善。 我該怎麼做?

伺服器範圍追蹤旗標 9481 或LEGACY_CARDINALITY_ESTIMATION資料庫範圍組態的更細微替代方案是使用查詢範圍的 USE HINT 建構。 如需詳細資訊,請參閱 SQL Server 2016USE HINT 中的 USE HINT 查詢提示自變數。

注意

也有追蹤 QUERYTRACEON 旗標 9481 的選項,但您應該考慮改用 USE HINT ,因為它在語意上更簡潔,而且不需要特殊許可權。

USE HINT FORCE_LEGACY_CARDINALITY_ESTIMATION 可讓您將查詢優化器 CE 模型設定為版本 70,而不論資料庫的相容性層級為何。 請參閱 查詢層級:使用查詢提示或QUERYTRACEON選項

或者,如果只有一個查詢與預設 CE 有問題,您可以強制儲存在 查詢存放區 中的舊版 CE 方案,或搭配計劃指南使用FORCE_LEGACY_CARDINALITY_ESTIMATION

CE 是一個複雜的問題,而且演算法依賴用於估計的不完美數據,例如數據表和索引的統計數據。 根據許多假設(例如述詞和數據行的相互關聯或獨立性、統一數據分佈、內含專案等等),某些模型外建構沒有資訊,例如數據表值函式 (TVF) 和模型。

鑒於客戶架構、數據和工作負載的無限制組合,幾乎不可能挑選適用於所有案例的模型。 雖然預設 CE 中的某些變更可能包含 Bug(就像任何其他軟體可以一樣),而且可以修正,但模型變更會造成其他問題。

CE 版本的變更,特別是從 70 到 120 的變更,包含許多不同的模型選擇。 例如,在估計篩選時,假設述詞之間有某種程度的相互關聯,因為實際上,這類相互關聯經常存在,而 CE 模型 70 會低估這類案例的結果。 雖然這些變更已針對許多工作負載進行測試,並改善了許多查詢,但對於某些其他查詢,舊版 CE 是較佳的比對,因此若是預設 CE,可能會觀察到效能回歸。

不幸的是,它不會被視為 Bug。 在這種情況下,請使用調整查詢等因應措施,就像您在查詢效能無法接受時需要處理舊版 CE 一樣,或強制先前的 CE 模型或特定執行計劃。

問9:是否有任何資源可了解預設CE中基數變更和查詢效能影響的詳細數據?

如需詳細資訊,請參閱 使用 SQL Server 2014 基數估算器 優化您的查詢計劃,並閱讀一節。