Поделиться через


Устранение неполадок с запросом, показывающим значительную разницу в производительности между двумя серверами

Применяется к: SQL Server

В этой статье приведены инструкции по устранению проблем с производительностью, когда запрос выполняется медленнее на одном сервере, чем на другом.

Симптомы

Предположим, что есть два сервера с установленными SQL Server. Один из экземпляров SQL Server содержит копию базы данных в другом экземпляре SQL Server. При выполнении запроса к базам данных на обоих серверах запрос выполняется медленнее на одном сервере, чем на другом.

Следующие действия помогут устранить эту проблему.

Шаг 1. Определение того, является ли это распространенной проблемой с несколькими запросами

Используйте один из следующих двух методов для сравнения производительности для двух или более запросов на двух серверах:

  • Протестируйте запросы на обоих серверах вручную:

    1. Выберите несколько запросов для тестирования с приоритетом для запросов, которые:
      • На одном сервере значительно быстрее, чем на другом.
      • Важно для пользователя или приложения.
      • Часто выполняется или предназначен для воспроизведения проблемы по запросу.
      • Достаточное время для записи данных в нем (например, вместо запроса 5 миллисекунд выберите 10-секундный запрос).
    2. Выполните запросы на двух серверах.
    3. Сравните затраченное время (длительность) на двух серверах для каждого запроса.
  • Анализ данных о производительности с помощью SQL Nexus.

    1. Сбор данных PSSDiag/SQLdiag или SQL LogScout для запросов на двух серверах.
    2. Импортируйте собранные файлы данных с помощью SQL Nexus и сравните запросы с двух серверов. Дополнительные сведения см. в разделе Сравнение производительности между двумя коллекциями журналов (например, медленный и быстрый).

Сценарий 1. Только один запрос выполняется по-разному на двух серверах

Если только один запрос выполняется по-разному, проблема, скорее всего, относится к отдельному запросу, а не к среде. В этом случае перейдите к шагу 2. Сбор данных и определите тип проблемы с производительностью.

Сценарий 2. Несколько запросов выполняются по-разному на двух серверах

Если несколько запросов выполняются медленнее на одном сервере, чем на другом, наиболее вероятной причиной являются различия в сервере или среде данных. Перейдите в раздел Диагностика различий в среде и убедитесь, что сравнение между двумя серверами является допустимым.

Шаг 2. Сбор данных и определение типа проблемы с производительностью

Сбор затраченного времени, времени ЦП и логических операций чтения

Чтобы собрать затраченное время и время ЦП запроса на обоих серверах, используйте один из следующих методов, наиболее подходящих для вашей ситуации:

  • Для текущих инструкций проверка total_elapsed_time и cpu_time столбцы в sys.dm_exec_requests. Выполните следующий запрос, чтобы получить данные:

    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;
    
  • Для предыдущих выполнений запроса проверка last_elapsed_time и last_worker_time столбцы в sys.dm_exec_query_stats. Выполните следующий запрос, чтобы получить данные:

    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) или Azure Data Studio, выполните его с помощью команды SET STATISTICS TIMEON и SET STATISTICS IOON.

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

    Затем в разделе Сообщения вы увидите время ЦП, затраченное время и логические операции чтения следующим образом:

      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.
    
  • Если вы можете собрать план запроса, проверка данные из свойств плана выполнения.

    1. Выполните запрос с включением фактического плана выполнения в.

    2. Выберите самый левый оператор в разделе План выполнения.

    3. В разделе Свойства разверните свойство QueryTimeStats .

    4. Установите флажки ElapsedTime и CpuTime.

      Снимок экрана: окно свойств плана выполнения SQL Server с развернутыми свойствами QueryTimeStats.

Сравните затраченное время и время ЦП запроса, чтобы определить тип проблемы для обоих серверов.

Тип 1: привязанный к ЦП (средство выполнения)

Если время ЦП близко, равно или больше затраченного времени, его можно рассматривать как запрос, связанный с ЦП. Например, если затраченное время составляет 3000 миллисекунда (мс), а время ЦП — 2900 мс, это означает, что большая часть затраченного времени тратится на ЦП. Затем можно сказать, что это запрос, привязанный к ЦП.

Примеры выполнения запросов (привязанных к ЦП):

Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
3200 3000 300000
1080 1000 20

Логические операции чтения — чтение страниц данных и индексов в кэше — чаще всего являются драйверами использования ЦП в SQL Server. Могут быть сценарии, в которых использование ЦП происходит из других источников: цикл while (в T-SQL или другом коде, например XProcs или объектах SQL CRL). Второй пример в таблице иллюстрирует такой сценарий, в котором большая часть ЦП не является результатом операций чтения.

Примечание.

Если время ЦП больше длительности, это означает, что выполняется параллельный запрос; несколько потоков используют ЦП одновременно. Дополнительные сведения см. в разделе Параллельные запросы — средство выполнения или официант.

Тип 2: ожидание на узком месте (официант)

Запрос ожидает узкого места, если затраченное время значительно больше времени ЦП. Затраченное время включает время выполнения запроса на ЦП (время ЦП) и время ожидания освобождения ресурса (время ожидания). Например, если затраченное время составляет 2000 мс, а время ЦП — 300 мс, время ожидания — 1700 мс (2000 – 300 = 1700). Дополнительные сведения см. в разделе Типы ожиданий.

Примеры ожидающих запросов:

Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
2000 300 28000
10080 700 80000

Параллельные запросы — средство выполнения или официант

Параллельные запросы могут использовать больше времени ЦП, чем общая длительность. Цель параллелизма — разрешить нескольким потокам одновременно выполнять части запроса. За одну секунду часов запрос может использовать восемь секунд времени ЦП, выполнив восемь параллельных потоков. Поэтому становится сложно определить привязанный к ЦП или ожидающий запрос на основе затраченного времени и разницы во времени ЦП. Однако, как правило, следуйте принципам, перечисленным в двух разделах выше. Сводка:

  • Если затраченное время гораздо больше времени ЦП, считайте его официантом.
  • Если время ЦП гораздо больше, чем затраченное время, считайте его средствами выполнения.

Примеры параллельных запросов:

Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
1200 8100 850000
3080 12300 1500000

Шаг 3. Сравнение данных с обоих серверов, выяснение сценария и устранение проблемы

Предположим, что есть два компьютера с именами Server1 и Server2. При этом запрос выполняется медленнее на Сервере1, чем на Сервере 2. Сравните время с обоих серверов, а затем следуйте действиям сценария, который лучше всего соответствует вашему из следующих разделов.

Сценарий 1. Запрос на сервере Server1 использует больше времени ЦП, а логические операции чтения на сервере Server1 выше, чем на Сервере 2

Если время ЦП на сервере Server1 гораздо больше, чем на Сервере2, а затраченное время совпадает с временем ЦП на обоих серверах, основные ожидания или узкие места отсутствуют. Увеличение времени ЦП на Сервере Server1, скорее всего, вызвано увеличением логических операций чтения. Значительное изменение логических операций чтения обычно указывает на разницу в планах запросов. Например:

Сервер Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
Server1 3100 3000 300000
Server2 1100 1000 90200

Действие: проверка планов выполнения и сред

  1. Сравните планы выполнения запроса на обоих серверах. Для этого используйте один из двух методов:
  2. Сравнение сред. Различные среды могут привести к различиям в плане запросов или прямым различиям в использовании ЦП. К средам относятся версии сервера, параметры конфигурации базы данных или сервера, флаги трассировки, количество ЦП или тактовая частота, а также виртуальная машина и физическая машина. Дополнительные сведения см. в статье Диагностика различий в плане запросов .

Сценарий 2. Запрос является официантом на сервере Server1, но не на сервере Server2

Если время ЦП для запроса на обоих серверах одинаково, но затраченное время на Сервере Server1 гораздо больше, чем на Сервере2, запрос на Server1 тратит гораздо больше времени на ожидание узкого места. Например:

Сервер Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
Server1 4500 1000 90200
Server2 1100 1000 90200
  • Время ожидания на сервере Server1: 4500 – 1000 = 3500 мс
  • Время ожидания на Сервере 2: 1100 – 1000 = 100 мс

Действие: проверка типов ожидания на сервере Server1

Определите и устраните узкое место на Сервере Server1. Примерами ожиданий являются блокировка (ожидание блокировки), ожиданий блокировки, ожиданий ввода-вывода на диске, ожиданий сети и ожиданий памяти. Чтобы устранить распространенные проблемы с узким местом, перейдите к разделу Диагностика ожиданий или узких мест.

Сценарий 3. Запросы на обоих серверах являются официантами, но типы или время ожидания различаются

Например:

Сервер Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
Server1 8000 1000 90200
Server2 3000 1000 90200
  • Время ожидания на сервере Server1: 8000 – 1000 = 7000 мс
  • Время ожидания на Сервере 2: 3000 – 1000 = 2000 мс

В этом случае время использования ЦП на обоих серверах одинаково, что указывает на то, что планы запросов, скорее всего, одинаковы. Запросы будут выполняться одинаково на обоих серверах, если они не дождутся узких мест. Таким образом, разница в продолжительности возникает из-за разного количества времени ожидания. Например, запрос ожидает блокировки на сервере Server1 в течение 7000 мс, а при вводе-выводе на Сервере2 — 2000 мс.

Действие: проверка типов ожидания на обоих серверах

Устраняйте каждое узкое место ожидания по отдельности на каждом сервере и ускоряйте выполнение на обоих серверах. Устранение этой проблемы является трудоемким, так как необходимо устранить узкие места на обоих серверах и сделать производительность сравнимой. Чтобы устранить распространенные проблемы с узким местом, перейдите к разделу Диагностика ожиданий или узких мест.

Сценарий 4. Запрос на сервере Server1 использует больше времени ЦП, чем на сервере Server2, но логические операции чтения близки

Например:

Сервер Затраченное время (мс) Время ЦП (мс) Чтение (логическое)
Server1 3000 3000 90200
Server2 1000 1000 90200

Если данные соответствуют следующим условиям:

  • Время ЦП на Сервере Server1 намного больше, чем на Сервере 2.
  • Затраченное время точно соответствует времени ЦП на каждом сервере, что указывает на отсутствие ожиданий.
  • Логические операции чтения, как правило, самый высокий драйвер времени ЦП, одинаковы на обоих серверах.

Затем дополнительное время ЦП приходится на некоторые другие действия, связанные с ЦП. Этот сценарий является самым редким из всех сценариев.

Причины: трассировка, определяемые пользователем функции и интеграция со средой CLR

Эта проблема может быть вызвана следующими причинами:

  • Трассировка XEvents/SQL Server, особенно с фильтрацией по текстовым столбцам (имя базы данных, имя входа, текст запроса и т. д.). Если трассировка включена на одном сервере, но не на другом, это может быть причиной разницы.
  • Определяемые пользователем функции (UDF) или другой код T-SQL, выполняющий операции, привязанные к ЦП. Обычно это происходит, когда другие условия на серверах Server1 и Server2 отличаются, например размер данных, тактовая частота ЦП или план питания.
  • SQL Server интеграции со средой CLR или расширенных хранимых процедур (XPs), которые могут управлять ЦП, но не выполняют логические операции чтения. Различия в библиотеках DLL могут привести к разному времени ЦП.
  • Разница в SQL Server функциональных возможностей, привязанных к ЦП (например, в коде обработки строк).

Действие: проверка трассировок и запросов

  1. Проверьте трассировку на обоих серверах на наличие следующих данных:

    1. Если трассировка включена на сервере Server1, но не на Сервере 2.
    2. Если какая-либо трассировка включена, отключите трассировку и снова запустите запрос на сервере Server1.
    3. Если запрос выполняется быстрее на этот раз, включите трассировку обратно, но удалите из него текстовые фильтры, если таковые имеются.
  2. Проверьте, использует ли запрос определяемые пользователем функции, которые выполняют манипуляции со строками или выполняют обширную обработку столбцов данных в списке SELECT .

  3. Проверьте, содержит ли запрос циклы, рекурсии функций или вложения.

Диагностика различий в среде

Проверьте следующие вопросы и определите, является ли сравнение двух серверов допустимым.

  • Являются ли два экземпляра SQL Server одной и той же версией или сборкой?

    В противном случае могут возникнуть некоторые исправления, которые вызвали различия. Выполните следующий запрос, чтобы получить сведения о версии на обоих серверах:

    SELECT @@VERSION
    
  • Совпадает ли объем физической памяти на обоих серверах?

    Если один сервер имеет 64 ГБ памяти, а другой — 256 ГБ памяти, это будет существенной разницей. Благодаря большему объему памяти для кэширования страниц данных, индексов и планов запросов запрос можно оптимизировать по-разному в зависимости от доступности аппаратных ресурсов.

  • Похожи ли конфигурации оборудования, связанные с ЦП, на обоих серверах? Например:

    • Количество ЦП зависит от компьютера (24 ЦП на одном компьютере и 96 ЦП на другом).

    • Планы управления питанием — сбалансированные и высокопроизводительные.

    • Виртуальная машина и физическая машина (без операционной системы).

    • Hyper-V и VMware — разница в конфигурации.

    • Разница в частоте (более низкая по сравнению с более высокой скоростью). Например, 2 ГГц и 3,5 ГГц могут изменить ситуацию. Чтобы получить тактовую скорость на сервере, выполните следующую команду PowerShell:

      Get-CimInstance Win32_Processor | Select-Object -Expand MaxClockSpeed
      

    Используйте один из следующих двух способов проверки скорости ЦП серверов. Если они не дают сопоставимых результатов, проблема не SQL Server. Это может быть разница в плане питания, меньшеЕ число ЦП, проблема с программным обеспечением виртуальной машины или разница в частоте частоты.

    • Выполните следующий сценарий 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
      END
      
      SELECT @time_millisecond = DATEDIFF(millisecond, @start_time, getdate())
      
      SELECT @spins Spins, @time_millisecond Time_ms,  @spins / @time_millisecond Spins_Per_ms
      

Диагностика ожиданий или узких мест

Чтобы оптимизировать запрос, ожидающий узких мест, определите, сколько времени ожидания и где находится узкое место (тип ожидания). После подтверждения типа ожидания сократите время ожидания или полностью исключите его.

Чтобы вычислить приблизительное время ожидания, вычесть время ЦП (время рабочей роли) из затраченного времени запроса. Как правило, время ЦП — это фактическое время выполнения, а оставшаяся часть времени существования запроса ожидается.

Примеры вычисления приблизительной продолжительности ожидания:

Затраченное время (мс) Время ЦП (мс) Время ожидания (мс)
3200 3000 200
7080 1000 6080

Определение узкого места или ожидания

  • Чтобы определить исторические запросы с длительным ожиданием (например, >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
             > 0.2
    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
    
  • Если вы можете собрать план запроса, проверка WaitStats из свойств плана выполнения в SSMS:

    1. Выполните запрос с включением фактического плана выполнения в.
    2. Щелкните правой кнопкой мыши левый оператор на вкладке План выполнения .
    3. Выберите Свойства , а затем — Свойство WaitStats .
    4. Проверьте Значения WaitTimeMs и WaitType.
  • Если вы знакомы со сценариями PSSDiag/SQLdiag или SQL LogScout LightPerf/GeneralPerf, рассмотрите возможность использования любого из них для сбора статистики производительности и определения ожидающих запросов на экземпляре SQL Server. Вы можете импортировать собранные файлы данных и анализировать данные о производительности с помощью SQL Nexus.

Ссылки для устранения или сокращения ожиданий

Причины и способы их устранения для каждого типа ожидания различаются. Не существует единого общего метода для разрешения всех типов ожидания. Ниже приведены статьи по устранению неполадок и устранению распространенных проблем с типом ожидания:

Описание многих типов ожиданий и то, что они указывают, см. в таблице Типы ожиданий.

Диагностика различий в планах запросов

Ниже приведены некоторые распространенные причины различий в планах запросов.

  • Различия в размерах данных или значениях данных

    Используется ли одна база данных на обоих серверах с одной и той же резервной копией базы данных? Были ли изменены данные на одном сервере по сравнению с другим? Различия в данных могут привести к разным планам запросов. Например, соединение таблицы 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'
    
  • Исправления оптимизатора включены или отключены

    Если исправления оптимизатора запросов включены на одном сервере, но отключены на другом, можно создать различные планы запросов. Дополнительные сведения см. в SQL Server модели обслуживания 4199 оптимизатора запросов.

    Чтобы получить состояние исправлений оптимизатора запросов, выполните следующий запрос:

    -- 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)
    
  • Различия между оборудованием (количество ЦП, размер памяти)

    Чтобы получить сведения об оборудовании, выполните следующий запрос:

    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 влияют на план, например SET ARITHABORT. Дополнительные сведения см. в разделе SET Options.

  • Различия в подсказках запросов

    Использует ли один запрос указания запросов, а другой нет? Проверьте текст запроса вручную, чтобы установить наличие указаний запроса.

  • Планы с учетом параметров (проблема с учетом параметров)

    Вы тестируете запрос с теми же значениями параметров? Если нет, то вы можете начать с этого. Был ли план ранее скомпилирован на одном сервере на основе другого значения параметра? Протестируйте два запроса с помощью указания запроса RECOMPILE, чтобы убедиться, что повторное использование плана не выполняется. Дополнительные сведения см. в статье Исследование и устранение проблем с учетом параметров.

  • Различные параметры базы данных и параметры конфигурации с заданной областью

    Используются ли одни и те же параметры базы данных или параметры конфигурации с областью действия на обоих серверах? Некоторые параметры базы данных могут повлиять на выбор плана. Например, совместимость баз данных, устаревшая CE и CE по умолчанию, а также sniffing. Выполните следующий запрос с одного сервера, чтобы сравнить параметры базы данных, используемые на двух серверах:

    -- 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