本文提供針對查詢在一個伺服器上的執行速度比另一個伺服器慢的效能問題的疑難排解步驟。

假設已安裝兩部 SQL Server 的伺服器。 其中一個 SQL Server 實例包含另一個 SQL Server 實例中的資料庫複本。 當您對兩部伺服器上的資料庫執行查詢時,查詢在一部伺服器上執行的速度比另一部伺服器慢。

下列步驟可協助針對此問題進行疑難解答。

步驟 1:判斷是否為多個查詢的常見問題

使用下列兩種方法之一來比較兩部伺服器上兩個或多個查詢的效能:

  • 在兩台伺服器上手動測試查詢:

  • 選擇數個查詢進行測試,優先考慮以下類型的查詢:
    • 一部伺服器上的速度明顯快於另一部伺服器。
    • 對使用者/應用程式很重要。
    • 經常執行或設計以便在需要時重現問題。
    • 足以擷取其上的數據(例如,而不是 5 毫秒的查詢,請選擇 10 秒的查詢)。
    • 在兩部伺服器上執行查詢。
    • 針對每個查詢,比較兩部伺服器上的經過時間(持續時間)。
    • 使用 SQL Nexus 分析效能數據。

    • 收集兩部伺服器的查詢用 PSSDiag/SQLdiag SQL LogScout 數據。
    • 使用 SQL Nexus 匯入收集的數據檔,並比較來自兩部伺服器的查詢。 如需詳細資訊,請參閱 兩個記錄集合之間的效能比較(例如慢速和快速)。
    • 案例 1:在兩部伺服器上,只有一個單一查詢以不同的方式執行

      如果只有一個查詢以不同的方式執行,問題就更可能專屬於個別查詢,而不是環境。 在此情況下,請移至 步驟 2:收集數據,並判斷效能問題 的類型。

      案例 2:多個查詢在兩部伺服器上的性能表現不同

      如果多個查詢在一部伺服器上執行的速度比另一個伺服器慢,最可能的原因是伺服器或數據環境的差異。 移至診斷 環境差異 ,並查看兩部伺服器之間的比較是否有效。

      步驟 2:收集數據並判斷效能問題的類型

      收集經過的時間、CPU 時間和邏輯讀取

      若要在兩部伺服器上收集查詢的經過時間和CPU時間,請使用下列最符合您情況的方法之一:

    • 針對目前執行的語句,請檢查 sys.dm_exec_requests中的 total_elapsed_time cpu_time 數據行。 執行下列查詢以取得資料:

      SELECT 
          req.session_id
          , req.total_elapsed_time AS duration_ms
          , req.cpu_time AS cpu_time_ms
          , req.total_elapsed_time - req.cpu_time AS wait_time
          , req.logical_reads
          , SUBSTRING (REPLACE (REPLACE (SUBSTRING (ST.text, (req.statement_start_offset/2) + 1, 
             ((CASE statement_end_offset
                 WHEN -1
                 THEN DATALENGTH(ST.text)  
                 ELSE req.statement_end_offset
               END - req.statement_start_offset)/2) + 1) , CHAR(10), ' '), CHAR(13), ' '), 
            1, 512)  AS statement_text  
      FROM sys.dm_exec_requests AS req
          CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS ST
      ORDER BY total_elapsed_time DESC;
      
    • 如需查詢的過去執行,請檢查sys.dm_exec_query_stats中的last_elapsed_timelast_worker_time欄位。 執行下列查詢以取得資料:

      SELECT t.text,
           (qs.total_elapsed_time/1000) / qs.execution_count AS avg_elapsed_time,
           (qs.total_worker_time/1000) / qs.execution_count AS avg_cpu_time,
           ((qs.total_elapsed_time/1000) / qs.execution_count ) - ((qs.total_worker_time/1000) / qs.execution_count) AS avg_wait_time,
           qs.total_logical_reads / qs.execution_count AS avg_logical_reads,
           qs.total_logical_writes / qs.execution_count AS avg_writes,
           (qs.total_elapsed_time/1000) AS cumulative_elapsed_time_all_executions
      FROM sys.dm_exec_query_stats qs
           CROSS apply sys.Dm_exec_sql_text (sql_handle) t
      WHERE t.text like '<Your Query>%'
      -- Replace <Your Query> with your query or the beginning part of your query. The special chars like '[','_','%','^' in the query should be escaped.
      ORDER BY (qs.total_elapsed_time / qs.execution_count) DESC
      

      如果 avg_wait_time 顯示負值,則為 平行查詢

    • 如果你能在 SQL Server Management Studio(SSMS)、 sqlcmd 或 Visual Studio Code 的 MSSQL 擴充功能中按需執行查詢,請使用 SET STATISTICS TIMEONSET STATISTICS IOON 執行。

      SET STATISTICS TIME ON
      SET STATISTICS IO ON
      <YourQuery>
      SET STATISTICS IO OFF
      SET STATISTICS TIME OFF
      

      然後,您會從 訊息中看到 CPU 時間、經過的時間,以及如下所示的邏輯讀取:

        Table 'tblTest'. Scan count 1, logical reads 3, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
        SQL Server Execution Times:
          CPU time = 460 ms,  elapsed time = 470 ms.
                    如果可以收集查詢計劃,請檢查執行 計劃屬性中的數據。

    • 使用 [包含實際執行計劃] 執行查詢

    • [執行計劃] 選取最左邊的運算子。

    • 屬性 展開 QueryTimeStats 屬性。

    • 檢查 ElapsedTimeCpuTime

      比較查詢經過的時間和CPU時間,以判斷這兩部伺服器的問題類型。

      類型 1:CPU 系結(執行器)

      如果 CPU 時間接近、等於或高於經過的時間,您可以將它視為 CPU 系結查詢。 例如,如果經過的時間是 3000 毫秒(毫秒),而 CPU 時間是 2900 毫秒,這表示大部分經過的時間都花在 CPU 上。 然後我們可以說這是 CPU 系結的查詢。

      執行 CPU 受限查詢的範例:

      經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)

      邏輯讀取 - 讀取緩存中資料/索引頁面的過程 - 最常是 SQL Server 中 CPU 使用率的主要因素。 在某些情況下,CPU 使用來自其他來源:while 迴圈(在 T-SQL 或其他程式代碼中,例如 XProcs 或 SQL CRL 物件)。 在數據表的第二個範例中展示了這種情況,其中大部分 CPU 時間不是花在讀取上。

      如果 CPU 時間大於持續時間,這表示已執行平行查詢;多個線程同時使用CPU。 如需詳細資訊,請參閱 平行查詢 - 執行器或等候者

      類型 2:等候瓶頸 (等候者)

      當經過的時間顯著多於 CPU 時間時,表示查詢正在等待瓶頸的解決。 經過的時間包括在 CPU 上執行查詢的時間(CPU 時間),以及等候釋放資源的時間(等候時間)。 例如,如果經過的時間是 2000 毫秒,而 CPU 時間是 300 毫秒,則等候時間為 1700 毫秒(2000 - 300 = 1700)。 如需詳細資訊,請參閱 等候類型。

      等候查詢的範例:

      經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)

      平行查詢 - 執行器或等候者

      平行查詢可能會使用比整體持續時間更多的CPU時間。 平行處理原則的目標是允許多個線程同時執行查詢的部分。 在時鐘時間的一秒內,查詢可能會藉由執行八個平行線程來使用八秒的CPU時間。 因此,根據經過的時間和CPU時間的差異,判斷是一個CPU受限或等候中的查詢會變得很困難。 不過,一般規則遵循上述兩節所列的原則。 摘要為:

    • 如果經過的時間遠大於 CPU 時間,請考慮它是等候者。
    • 如果 CPU 時間遠大於經過的時間,請考慮它為執行器。
    • 平行查詢的範例:

      經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)

      步驟 3:比較這兩部伺服器的數據、找出案例,以及針對問題進行疑難解答

      假設有兩部名為 Server1 和 Server2 的電腦。 而查詢在 Server1 上執行的速度比 Server2 慢。 比較兩部伺服器的時間,然後按照以下各節中最符合您情境的情形進行操作。

      案例 1:Server1 上的查詢會使用較多的 CPU 時間,而 Server1 上的邏輯讀取比 Server2 上的更高

      如果 Server1 上的 CPU 時間遠大於 Server2,且經過的時間與兩部伺服器上的 CPU 時間緊密相符,則沒有任何主要等候或瓶頸。 Server1 上的 CPU 時間增加很可能是因為邏輯讀取增加所造成。 邏輯讀取的重大變更通常表示查詢計劃的差異。 例如:

      經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)
    • 比較這兩部伺服器上的查詢執行計劃。 若要這樣做,請使用下列兩種方法之一:
      • 以可視化方式比較執行計劃。 如需詳細資訊,請參閱顯示實際執行計劃
      • 儲存執行計劃,並使用 SQL Server Management Studio 方案比較功能加以比較。
      • 比較不同環境。 不同的環境可能會導致查詢計劃差異或CPU使用量的直接差異。 環境包括伺服器版本、資料庫或伺服器組態設定、追蹤旗標、CPU 計數或時鐘速度,以及虛擬機與實體機器。 如需詳細資訊,請參閱診斷查詢計劃差異。
      • 案例 2:在 Server1 上,查詢是等待中的請求,但在 Server2 上則不是

        如果這兩部伺服器上的查詢 CPU 時間類似,但 Server1 上經過的時間遠大於 Server2,則 Server1 上的查詢會花費較長的時間 等候瓶頸。 例如:

        經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)

        動作:檢查 Server1 上的等候類型

        識別並消除 Server1 上的瓶頸。 等候範例包括封鎖(鎖定等候)、閂鎖等候、磁碟 I/O 等候、網路等候和記憶體等候。 若要針對常見的瓶頸問題進行疑難解答,請參閱 等候或瓶頸診斷

        案例 3:這兩部伺服器上的查詢都是等待中的項目,但等候類型或時間不同

        經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)
      • Server2 上的等候時間:3000 - 1000 = 2000 毫秒
      • 在此情況下,這兩部伺服器上的CPU時間都類似,這表示查詢計劃可能相同。 如果兩部伺服器沒有等待瓶頸,查詢就會同樣地執行。 因此,持續時間差異來自不同的等候時間量。 例如,查詢在 Server1 上因鎖定而等候 7000 毫秒,同時在 Server2 上因 I/O 等候 2000 毫秒。

        動作:檢查兩部伺服器上的等候類型

        解決每個伺服器的瓶頸等候問題,並分別加快兩部伺服器上的執行速度。 此問題的疑難解答需要大量人力,因為您需要消除兩部伺服器上的瓶頸,並讓效能可比較。 若要針對常見的瓶頸問題進行疑難排解,請前往 診斷等候或瓶頸

        案例 4:Server1 上的查詢使用比 Server2 更多的 CPU 時間,但邏輯讀取接近。

        經過的時間 (毫秒) CPU 時間 (毫秒) 讀取 (邏輯)
      • Server1 上的 CPU 時間遠大於 Server2。
      • 經過時間與每部伺服器上的CPU時間非常接近,這表示沒有等候。
      • 邏輯讀取通常是 CPU 時間的主要消耗者,這兩部伺服器上的情況都很相似。
      • 然後,額外的CPU時間來自其他CPU密集型活動。 此案例是所有案例中最罕見的情況。

        原因:追蹤功能、UDF 和 CLR 整合

        此問題可能是由下列原因所造成:

      • XEvents/SQL Server 追蹤,特別是對文字欄位的篩選(資料庫名稱、登入名稱、查詢文字等等)。 如果在一部伺服器上啟用追蹤,但未啟用另一部伺服器,這可能是差異的原因。
      • 執行 CPU 系結作業的使用者定義函式 (UDF) 或其他 T-SQL 程式代碼。 這通常是 Server1 和 Server2 上其他條件不同的原因,例如數據大小、CPU 時鐘速度或電源計劃。
      • SQL Server CLR 整合擴充預存程式(XP) 可能會驅動 CPU,但不會執行邏輯讀取。 DLL 的差異可能會導致不同的CPU時間。
      • CPU 系結的 SQL Server 功能差異(例如字串操作程式碼)。
      • 動作:檢查追蹤紀錄和查詢

      • 檢查這兩部伺服器上的追蹤記錄:

      • 如果 Server1 上已啟用任何追蹤功能,但未在 Server2 上啟用。
      • 如果已啟用任何追蹤,請停用追蹤,然後在 Server1 上再次執行查詢。
      • 如果這次查詢執行得更快,請啟用追蹤功能,但若有文字篩選,請將其移除。
      • 檢查查詢是否使用執行字串操作的 UDF,或在清單中對資料行 SELECT 執行大量處理。

      • 檢查查詢是否包含迴圈、函式遞歸或巢狀。

        診斷環境差異

        檢查下列問題,並判斷兩部伺服器之間的比較是否有效。

      • 這兩個 SQL Server 實例是否為相同版本或組建?

        如果沒有,可能有一些修正導致了這些差異。 執行下列查詢以取得這兩部伺服器上的版本資訊:

        SELECT @@VERSION
        
      • 這兩部伺服器上的物理記憶體數量是否相似?

        如果一部伺服器有 64 GB 的記憶體,而另一部伺服器有 256 GB 的記憶體,那將會是顯著的差異。 使用更多記憶體可快取數據/索引頁面和查詢計劃,查詢可能會根據硬體資源可用性以不同的方式進行優化。

      • 這兩部伺服器上的 CPU 相關硬體設定是否類似? 例如:

      • CPU 數目會因計算機而異(一部計算機上的 24 個 CPU,另一部計算機為 96 個 CPU)。

      • 電源計劃 - 平衡與高效能。

      • 虛擬機 (VM) 與實體 (裸機) 機器。

      • Hyper-V 與 VMware- 組態的差異。

      • 時鐘速度差異(時鐘速度較低與時鐘速度較高)。 例如,2 GHz 與 3.5 GHz 可能會有所差異。 若要取得伺服器上的時鐘速度,請執行下列 PowerShell 命令:

        Get-CimInstance Win32_Processor | Select-Object -Expand MaxClockSpeed
        

        使用下列兩種方式之一來測試伺服器的CPU速度。 如果它們不會產生可比較的結果,問題就不在 SQL Server 之外。 這可能是電源計劃差異、CPU 較少、VM 軟體問題或時鐘速度差異。

      • 在兩部伺服器上執行下列 PowerShell 腳本,並比較輸出。

        $bf = [System.DateTime]::Now
        for ($i = 0; $i -le 20000000; $i++) {}
        $af = [System.DateTime]::Now
        Write-Host ($af - $bf).Milliseconds " milliseconds"
        Write-Host ($af - $bf).Seconds " Seconds"
        
      • 在兩部伺服器上執行下列 Transact-SQL 程式代碼,並比較輸出。

        SET NOCOUNT ON 
        DECLARE @spins INT = 0
        DECLARE @start_time DATETIME = GETDATE(), @time_millisecond INT
        WHILE (@spins < 20000000)
        BEGIN
           SET @spins = @spins +1
        SELECT @time_millisecond = DATEDIFF(millisecond, @start_time, getdate())
        SELECT @spins Spins, @time_millisecond Time_ms,  @spins / @time_millisecond Spins_Per_ms
        

        若要優化等候瓶頸的查詢,請找出等候的時間長度,以及瓶頸所在的位置(等候類型)。 確認等候類型之後,請減少等候時間,或完全排除等候。

        若要計算大約等候時間,請從查詢經過的時間減去 CPU 時間(背景工作時間)。 一般而言,CPU 時間是實際運行時間,而查詢存留期的剩餘部分正在等候。

        如何計算近似等候持續時間的範例:

        經過的時間 (毫秒) CPU 時間 (毫秒) 等候時間 (毫秒)

        識別瓶頸或等候

      • 若要識別歷程記錄長時間等候的查詢(例如, >20% 的整體經過時間是等候時間),請執行下列查詢。 此查詢會使用自 SQL Server 啟動以來的快取查詢計劃的效能統計資料。

        SELECT t.text,
                 qs.total_elapsed_time / qs.execution_count
                 AS avg_elapsed_time,
                 qs.total_worker_time / qs.execution_count
                 AS avg_cpu_time,
                 (qs.total_elapsed_time - qs.total_worker_time) / qs.execution_count
                 AS avg_wait_time,
                 qs.total_logical_reads / qs.execution_count
                 AS avg_logical_reads,
                 qs.total_logical_writes / qs.execution_count
                 AS avg_writes,
                 qs.total_elapsed_time
                 AS cumulative_elapsed_time
        FROM sys.dm_exec_query_stats qs
                 CROSS apply sys.Dm_exec_sql_text (sql_handle) t
        WHERE (qs.total_elapsed_time - qs.total_worker_time) / qs.total_elapsed_time
        ORDER BY qs.total_elapsed_time / qs.execution_count DESC
        
      • 若要識別目前執行等待時間超過 500 毫秒的查詢,請執行下列查詢:

        SELECT r.session_id, r.wait_type, r.wait_time AS wait_time_ms
        FROM sys.dm_exec_requests r 
           JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id 
        WHERE wait_time > 500
        AND is_user_process = 1
        
      • 如果可以收集查詢計劃,請檢查 SSMS 中執行計劃屬性中的 WaitStats

      • 將查詢與包含實際執行計劃打開並執行。
      • 在 [執行計劃] 索引標籤中,以滑鼠右鍵點擊最左邊的運算子。
      • 選取 屬性,然後選取 WaitStats 屬性。
      • 檢查 WaitTimeMsWaitType
      • 如果您熟悉 PSSDiag/SQLdiagSQL LogScout LightPerf/GeneralPerf 案例,請考慮使用其中一個來收集效能統計數據,並識別 SQL Server 實例上的等候查詢。 您可以匯入收集的數據檔,並使用 SQL Nexus 分析效能數據

        協助消除或減少等候的參考

        每個等候類型的原因和解決方式會有所不同。 沒有一個一般方法可以解析所有等候類型。 以下是疑難解答和解決常見等候類型問題的文章:

        瞭解並解決封鎖問題 (LCK_M_*)
      • 了解並解決 Azure SQL 資料庫封鎖問題
      • 針對 I/O 問題所造成的 SQL Server 效能緩慢進行疑難解答(PAGEIOLATCH_*、WRITELOG、IO_COMPLETION、BACKUPIO)
      • 解決 SQL Server 中最後一頁插入 PAGELATCH_EX 爭用問題
      • 記憶體分配說明及解決方案(RESOURCE_SEMAPHORE)
      • 針對ASYNC_NETWORK_IO等候類型所產生的慢速查詢進行疑難解答
      • 針對具有AlwaysOn可用性群組的高HADR_SYNC_COMMIT等候類型進行疑難解答
      • 運作方式:CMEMTHREAD 和其偵錯過程 讓平行處理原則等候可採取動作 (CXPACKET 和 CXCONSUMER) THREADPOOL 等候

        如需許多 Wait 類型及其指示的描述,請參閱 Waits 類型中的表格。

        診斷查詢計劃差異

        以下是查詢計劃差異的一些常見原因:

      • 數據大小或數據值差異

        這兩部伺服器上是否使用相同的資料庫—使用相同的資料庫備份? 資料在一台伺服器上與另一台相比是否已被修改? 數據差異可能會導致不同的查詢計劃。 例如,聯結數據表 T1 (1000 個數據列)與數據表 T2 (2,000,000 個數據列) 與聯結數據表 T1 (100 個數據列) 與數據表 T2 (2,000,000 個數據列) 不同。 作業的類型 JOIN 和速度可能會有很大的不同。

      • 統計數據差異

        統計數據是否已更新在一個資料庫上,但沒有在另一個資料庫上? 統計數據是否已以不同的取樣率更新(例如,30% 與 100% 完整掃描)? 請確定您使用相同的取樣率來更新這兩端的統計數據。

      • 資料庫相容性層級差異

        檢查兩部伺服器之間的資料庫相容性層級是否不同。 若要取得資料庫相容性層級,請執行下列查詢:

        SELECT name, compatibility_level
        FROM sys.databases
        WHERE name = '<YourDatabase>'
        
      • 伺服器版本/組建差異

        兩部伺服器之間的 SQL Server 版本或組建是否不同? 例如,一部伺服器是 SQL Server 版本 2014,而另一部伺服器是 SQL Server 版本 2016 嗎? 可能會有產品變更,可能會導致選取查詢計劃的方式變更。 請務必比較相同的 SQL Server 版本和組建。

        SELECT ServerProperty('ProductVersion')
        
      • 基數估算器 (CE) 版本差異

        檢查舊版基數估算器是否在資料庫層級啟動。 如需 CE 的詳細資訊,請參閱 基數估計 (SQL Server)

        SELECT name, value, is_value_default
        FROM sys.database_scoped_configurations
        WHERE name = 'LEGACY_CARDINALITY_ESTIMATION'
        
      • 優化工具修正程式已啟用/停用

        如果在一部伺服器上啟用了查詢優化器 Hotfix,而在另一部伺服器上卻停用了,則可能會產生不同的查詢計畫。 如需詳細資訊,請參閱 SQL Server 查詢優化器 Hotfix 追蹤旗標 4199 服務模型

        若要取得查詢優化器 Hotfix 的狀態,請執行下列查詢:

        -- Check at server level for TF 4199
        DBCC TRACESTATUS (-1)
        -- Check at database level
        USE <YourDatabase>
        SELECT name, value, is_value_default 
        FROM sys.database_scoped_configurations
        WHERE name = 'QUERY_OPTIMIZER_HOTFIXES'
        
      • 追蹤標誌差異

        某些追蹤旗標會影響查詢計劃選取。 檢查某部伺服器上是否已啟用追蹤旗標,但未在其他伺服器上啟用。 在兩部伺服器上執行下列查詢,並比較結果:

        -- Check at server level for trace flags
        DBCC TRACESTATUS (-1)
        
      • 硬體差異(CPU 計數、記憶體大小)

        若要取得硬體資訊,請執行下列查詢:

        SELECT cpu_count, physical_memory_kb/1024/1024 PhysicalMemory_GB 
        FROM sys.dm_os_sys_info
        
      • 查詢優化器觀察到的硬體差異

        檢查查詢計劃中的 OptimizerHardwareDependentProperties,並查看硬體差異是否在不同的計畫中顯得相當重要。

        WITH xmlnamespaces(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
        SELECT
          txt.text,
          t.OptHardw.value('@EstimatedAvailableMemoryGrant', 'INT') AS EstimatedAvailableMemoryGrant , 
          t.OptHardw.value('@EstimatedPagesCached', 'INT') AS EstimatedPagesCached, 
          t.OptHardw.value('@EstimatedAvailableDegreeOfParallelism', 'INT') AS EstimatedAvailDegreeOfParallelism,
          t.OptHardw.value('@MaxCompileMemory', 'INT') AS MaxCompileMemory
        FROM sys.dm_exec_cached_plans AS cp
        CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
        CROSS APPLY qp.query_plan.nodes('//OptimizerHardwareDependentProperties') AS t(OptHardw)
        CROSS APPLY sys.dm_exec_sql_text (CP.plan_handle) txt
        WHERE text Like '%<Part of Your Query>%'
        
      • 優化器逾時

        是否有優化器逾時問題? 如果執行的查詢太複雜,查詢優化器可以停止評估計劃選項。 停止時,它會挑選當時成本最低的方案。 這可能會導致某台伺服器上的計劃選擇看起來任意,而與另外一台伺服器的選擇不同。

        某些 SET 選項會影響計劃,例如 SET ARITHABORT。 如需詳細資訊,請參閱 SET 選項

      • 查詢提示差異

        一個查詢是否使用 查詢提示 ,而另一個查詢則不使用? 手動檢查查詢文字,以確認查詢提示的存在。

      • 參數敏感計劃 (參數探查問題)

        您是否使用完全相同的參數值來測試查詢? 如果沒有,您可以從該處開始。 計劃先前是以不同的參數值為基礎在一部伺服器上編譯的嗎? 使用 RECOMPILE 查詢提示測試這兩個查詢,以確保不會重複執行計劃。 如需詳細資訊,請參閱調查和解決參數敏感性問題

      • 不同的資料庫選項/範圍組態設定

        這兩部伺服器上所使用的資料庫選項或範圍組態設定是否相同? 某些資料庫選項可能會影響計劃選擇。 例如,資料庫相容性、舊版CE與預設CE,以及參數探查。 從一部伺服器執行下列查詢,以比較兩部伺服器上所使用的資料庫選項:

        -- On Server1 add a linked server to Server2 
        EXEC master.dbo.sp_addlinkedserver @server = N'Server2', @srvproduct=N'SQL Server'
        -- Run a join between the two servers to compare settings side by side
        SELECT 
           s1.name AS srv1_config_name, 
           s2.name AS srv2_config_name,
           s1.value_in_use AS srv1_value_in_use, 
           s2.value_in_use AS srv2_value_in_use, 
           Variance = CASE WHEN ISNULL(s1.value_in_use, '##') != ISNULL(s2.value_in_use,'##') THEN 'Different' ELSE '' END
        FROM sys.configurations s1 
        FULL OUTER JOIN [server2].master.sys.configurations s2 ON s1.name = s2.name
        SELECT 
           s1.name AS srv1_config_name,
           s2.name AS srv2_config_name,
           s1.value srv1_value_in_use,
           s2.value srv2_value_in_use,
           s1.is_value_default,
           s2.is_value_default,
           Variance = CASE WHEN ISNULL(s1.value, '##') != ISNULL(s2.value, '##') THEN 'Different' ELSE '' END
        FROM sys.database_scoped_configurations s1
        FULL OUTER JOIN [server2].master.sys.database_scoped_configurations s2 ON s1.name = s2.name
        

        是否在一部伺服器上的查詢使用了任何計畫指引,而在另一部伺服器上則未使用? 執行下列查詢來建立差異:

        SELECT * FROM sys.plan_guides
        
  •