Share via


Solución de problemas de una consulta que muestra una diferencia significativa de rendimiento entre dos servidores

Se aplica a: SQL Server

En este artículo se proporcionan los pasos para solucionar un problema de rendimiento en el que una consulta se ejecuta más lentamente en un servidor que en otro.

Síntomas

Supongamos que hay dos servidores con SQL Server instalados. Una de las instancias de SQL Server contiene una copia de una base de datos en la otra instancia de SQL Server. Al ejecutar una consulta en las bases de datos de ambos servidores, la consulta se ejecuta más lentamente en un servidor que en el otro.

Los pasos siguientes pueden ayudar a solucionar este problema.

Paso 1: Determinar si se trata de un problema común con varias consultas

Use uno de los dos métodos siguientes para comparar el rendimiento de dos o más consultas en los dos servidores:

  • Pruebe manualmente las consultas en ambos servidores:

    1. Elija varias consultas para realizar pruebas con prioridad en las consultas que son:
      • Significativamente más rápido en un servidor que en el otro.
      • Importante para el usuario o la aplicación.
      • Se ejecuta o se diseña con frecuencia para reproducir el problema a petición.
      • Es lo suficientemente largo como para capturar datos (por ejemplo, en lugar de una consulta de 5 milisegundos, elija una consulta de 10 segundos).
    2. Ejecute las consultas en los dos servidores.
    3. Compare el tiempo transcurrido (duración) en dos servidores para cada consulta.
  • Analice los datos de rendimiento con SQL Nexus.

    1. Recopile datos PSSDiag/SQLdiag o SQL LogScout para las consultas en los dos servidores.
    2. Importe los archivos de datos recopilados con SQL Nexus y compare las consultas de los dos servidores. Para obtener más información, vea Comparación de rendimiento entre dos recopilaciones de registros (slow y fast, por ejemplo).

Escenario 1: solo una sola consulta funciona de forma diferente en los dos servidores

Si solo una consulta funciona de forma diferente, es más probable que el problema sea más específico para la consulta individual que para el entorno. En este caso, vaya al Paso 2: Recopilar datos y determinar el tipo de problema de rendimiento.

Escenario 2: Varias consultas se realizan de forma diferente en los dos servidores

Si varias consultas se ejecutan más lentamente en un servidor que en el otro, la causa más probable son las diferencias en el servidor o el entorno de datos. Vaya a Diagnosticar diferencias de entorno y vea si la comparación entre los dos servidores es válida.

Paso 2: Recopilar datos y determinar el tipo de problema de rendimiento

Recopilar tiempo transcurrido, tiempo de CPU y lecturas lógicas

Para recopilar el tiempo transcurrido y el tiempo de CPU de la consulta en ambos servidores, use uno de los métodos siguientes que mejor se adapten a su situación:

  • Para las instrucciones que se ejecutan actualmente, compruebe las columnas total_elapsed_time y cpu_time en sys.dm_exec_requests. Ejecute la consulta siguiente para obtener los datos:

    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;
    
  • Para las ejecuciones anteriores de la consulta, compruebe las columnas last_elapsed_time y last_worker_time en sys.dm_exec_query_stats. Ejecute la consulta siguiente para obtener los datos:

    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
    

    Nota:

    Si avg_wait_time muestra un valor negativo, es una consulta paralela.

  • Si puede ejecutar la consulta a petición en SQL Server Management Studio (SSMS) o Azure Data Studio, ejecútela con SET STATISTICS TIMEON y SET STATISTICS IOON.

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

    A continuación, en Mensajes, verá el tiempo de CPU, el tiempo transcurrido y las lecturas lógicas de la siguiente manera:

      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.
    
  • Si puede recopilar un plan de consulta, compruebe los datos de las propiedades del plan de ejecución.

    1. Ejecute la consulta con Incluir plan de ejecución real activado.

    2. Seleccione el operador más a la izquierda en Plan de ejecución.

    3. En Propiedades, expanda la propiedad QueryTimeStats .

    4. Compruebe ElapsedTime y CpuTime.

      Captura de pantalla de la ventana de propiedades del plan de ejecución de SQL Server con la propiedad QueryTimeStats expandida.

Compare el tiempo transcurrido y el tiempo de CPU de la consulta para determinar el tipo de problema de ambos servidores.

Tipo 1: enlazado a la CPU (ejecutor)

Si el tiempo de CPU está cerca, igual o mayor que el tiempo transcurrido, puede tratarlo como una consulta enlazada a la CPU. Por ejemplo, si el tiempo transcurrido es de 3000 milisegundos (ms) y el tiempo de CPU es de 2900 ms, significa que la mayor parte del tiempo transcurrido se dedica a la CPU. A continuación, podemos decir que es una consulta enlazada a la CPU.

Ejemplos de consultas en ejecución (enlazadas a CPU):

Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
3200 3000 300000
1080 1000 20

Las lecturas lógicas (leer páginas de datos o índices en la memoria caché) son con más frecuencia los controladores del uso de CPU en SQL Server. Podría haber escenarios en los que el uso de CPU procede de otros orígenes: un bucle while (en T-SQL u otro código como XProcs o objetos CRL de SQL). En el segundo ejemplo de la tabla se muestra este escenario, donde la mayoría de la CPU no procede de lecturas.

Nota:

Si el tiempo de CPU es mayor que la duración, esto indica que se ejecuta una consulta paralela; varios subprocesos usan la CPU al mismo tiempo. Para obtener más información, consulte Consultas paralelas: ejecutor o camarero.

Tipo 2: Esperando un cuello de botella (camarero)

Una consulta está esperando un cuello de botella si el tiempo transcurrido es significativamente mayor que el tiempo de CPU. El tiempo transcurrido incluye el tiempo de ejecución de la consulta en la CPU (tiempo de CPU) y el tiempo que espera a que se libere un recurso (tiempo de espera). Por ejemplo, si el tiempo transcurrido es de 2000 ms y el tiempo de CPU es de 300 ms, el tiempo de espera es de 1700 ms (2000 - 300 = 1700). Para obtener más información, vea Tipos de esperas.

Ejemplos de consultas en espera:

Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
2000 300 28000
10080 700 80000

Consultas paralelas: ejecutor o camarero

Las consultas paralelas pueden usar más tiempo de CPU que la duración general. El objetivo del paralelismo es permitir que varios subprocesos ejecuten partes de una consulta simultáneamente. En un segundo de hora del reloj, una consulta puede usar ocho segundos de tiempo de CPU mediante la ejecución de ocho subprocesos paralelos. Por lo tanto, resulta difícil determinar una consulta enlazada a la CPU o en espera en función del tiempo transcurrido y la diferencia de tiempo de CPU. Sin embargo, como regla general, siga los principios enumerados en las dos secciones anteriores. El resumen es:

  • Si el tiempo transcurrido es mucho mayor que el tiempo de CPU, considérelo un camarero.
  • Si el tiempo de CPU es mucho mayor que el tiempo transcurrido, considéralo un ejecutor.

Ejemplos de consultas paralelas:

Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
1200 8100 850000
3080 12300 1500000

Paso 3: Comparar datos de ambos servidores, averiguar el escenario y solucionar el problema

Supongamos que hay dos máquinas denominadas Server1 y Server2. Y la consulta se ejecuta más lentamente en Server1 que en Server2. Compare las horas de ambos servidores y, a continuación, siga las acciones del escenario que mejor coincida con las suyas en las secciones siguientes.

Escenario 1: La consulta en Server1 usa más tiempo de CPU y las lecturas lógicas son mayores en Server1 que en Server2

Si el tiempo de CPU en Server1 es mucho mayor que en Server2 y el tiempo transcurrido coincide estrechamente con el tiempo de CPU en ambos servidores, no hay esperas ni cuellos de botella importantes. Es más probable que el aumento del tiempo de CPU en Server1 se deba a un aumento de las lecturas lógicas. Un cambio significativo en las lecturas lógicas suele indicar una diferencia en los planes de consulta. Por ejemplo:

Servidor Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
Server1 3100 3000 300000
Server2 1100 1000 90200

Acción: Comprobación de los planes y entornos de ejecución

  1. Compare los planes de ejecución de la consulta en ambos servidores. Para ello, use uno de los dos métodos:
  2. Comparar entornos. Diferentes entornos pueden dar lugar a diferencias de planes de consulta o diferencias directas en el uso de CPU. Entre los entornos se incluyen las versiones del servidor, la configuración de la base de datos o del servidor, las marcas de seguimiento, el número de CPU o la velocidad del reloj y la máquina virtual frente a la máquina física. Consulte Diagnóstico de diferencias del plan de consulta para obtener más información.

Escenario 2: La consulta es un camarero en Server1, pero no en Server2

Si los tiempos de CPU de la consulta en ambos servidores son similares, pero el tiempo transcurrido en Server1 es mucho mayor que en Server2, la consulta en Server1 pasa mucho más tiempo esperando un cuello de botella. Por ejemplo:

Servidor Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
Server1 4500 1000 90200
Server2 1100 1000 90200
  • Tiempo de espera en Server1: 4500 - 1000 = 3500 ms
  • Tiempo de espera en Server2: 1100 - 1000 = 100 ms

Acción: Comprobar los tipos de espera en Server1

Identifique y elimine el cuello de botella en Server1. Algunos ejemplos de esperas son el bloqueo (esperas de bloqueo), las esperas de bloqueo temporal, las esperas de E/S de disco, las esperas de red y las esperas de memoria. Para solucionar problemas comunes de cuellos de botella, vaya a Diagnosticar esperas o cuellos de botella.

Escenario 3: Las consultas en ambos servidores son camareros, pero los tipos de espera o los tiempos son diferentes

Por ejemplo:

Servidor Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
Server1 8000 1000 90200
Server2 3000 1000 90200
  • Tiempo de espera en Server1: 8000 - 1000 = 7000 ms
  • Tiempo de espera en Server2: 3000 - 1000 = 2000 ms

En este caso, los tiempos de CPU son similares en ambos servidores, lo que indica que es probable que los planes de consulta sean los mismos. Las consultas se realizarían igualmente en ambos servidores si no esperaran a los cuellos de botella. Por lo tanto, las diferencias de duración proceden de las diferentes cantidades de tiempo de espera. Por ejemplo, la consulta espera en bloqueos en Server1 por 7000 ms mientras espera 2000 ms en E/S en Server2.

Acción: comprobar los tipos de espera en ambos servidores

Solucione cada espera de cuello de botella individualmente en cada servidor y acelere las ejecuciones en ambos servidores. La solución de este problema requiere mucho trabajo, ya que debe eliminar cuellos de botella en ambos servidores y hacer que el rendimiento sea comparable. Para solucionar problemas comunes de cuellos de botella, vaya a Diagnosticar esperas o cuellos de botella.

Escenario 4: La consulta en Server1 usa más tiempo de CPU que en Server2, pero las lecturas lógicas están cercanas

Por ejemplo:

Servidor Tiempo transcurrido (ms) Tiempo de CPU (ms) Lecturas (lógicas)
Server1 3000 3000 90200
Server2 1000 1000 90200

Si los datos coinciden con las condiciones siguientes:

  • El tiempo de CPU en Server1 es mucho mayor que en Server2.
  • El tiempo transcurrido coincide estrechamente con el tiempo de CPU en cada servidor, lo que indica que no hay esperas.
  • Las lecturas lógicas, normalmente el controlador más alto del tiempo de CPU, son similares en ambos servidores.

A continuación, el tiempo de CPU adicional procede de otras actividades enlazadas a la CPU. Este escenario es el más raro de todos los escenarios.

Causas: seguimiento, UDF e integración clr

Este problema puede deberse a lo siguiente:

  • Seguimiento de XEvents/SQL Server, especialmente con el filtrado de columnas de texto (nombre de base de datos, nombre de inicio de sesión, texto de consulta, etc.). Si el seguimiento está habilitado en un servidor, pero no en el otro, podría ser el motivo de la diferencia.
  • Funciones definidas por el usuario (UDF) u otro código T-SQL que realiza operaciones enlazadas a la CPU. Normalmente, esta sería la causa cuando otras condiciones son diferentes en Server1 y Server2, como el tamaño de datos, la velocidad del reloj de CPU o el plan de energía.
  • SQL Server integración clr o procedimientos almacenados extendidos (XP) que pueden impulsar la CPU pero no realizar lecturas lógicas. Las diferencias en los archivos DLL pueden dar lugar a diferentes tiempos de CPU.
  • Diferencia en SQL Server funcionalidad que está enlazada a la CPU (por ejemplo, código de manipulación de cadenas).

Acción: Comprobación de seguimientos y consultas

  1. Compruebe los seguimientos en ambos servidores para lo siguiente:

    1. Si hay algún seguimiento habilitado en Server1, pero no en Server2.
    2. Si hay algún seguimiento habilitado, deshabilite el seguimiento y vuelva a ejecutar la consulta en Server1.
    3. Si la consulta se ejecuta más rápido esta vez, habilite el seguimiento de nuevo, pero quite los filtros de texto, si hay alguno.
  2. Compruebe si la consulta usa UDF que realizan manipulaciones de cadenas o realizan un procesamiento exhaustivo en las columnas de datos de la SELECT lista.

  3. Compruebe si la consulta contiene bucles, recursiones de función o anidamientos.

Diagnóstico de diferencias de entorno

Compruebe las siguientes preguntas y determine si la comparación entre los dos servidores es válida.

  • ¿Las dos instancias de SQL Server son la misma versión o compilación?

    Si no es así, podría haber algunas correcciones que causaron las diferencias. Ejecute la consulta siguiente para obtener información de versión en ambos servidores:

    SELECT @@VERSION
    
  • ¿La cantidad de memoria física es similar en ambos servidores?

    Si un servidor tiene 64 GB de memoria, mientras que el otro tiene 256 GB de memoria, sería una diferencia significativa. Con más memoria disponible para almacenar en caché las páginas de datos o índices y los planes de consulta, la consulta podría optimizarse de forma diferente en función de la disponibilidad de recursos de hardware.

  • ¿Las configuraciones de hardware relacionadas con la CPU son similares en ambos servidores? Por ejemplo:

    • El número de CPU varía entre máquinas (24 CPU en una máquina frente a 96 CPU en la otra).

    • Planes de energía: equilibrados frente a alto rendimiento.

    • Máquina virtual (VM) frente a máquina física (sin sistema operativo).

    • Hyper-V frente a VMware: diferencia en la configuración.

    • Diferencia de velocidad del reloj (menor velocidad del reloj frente a mayor velocidad del reloj). Por ejemplo, 2 GHz frente a 3,5 GHz pueden marcar la diferencia. Para obtener la velocidad del reloj en un servidor, ejecute el siguiente comando de PowerShell:

      Get-CimInstance Win32_Processor | Select-Object -Expand MaxClockSpeed
      

    Use una de las dos maneras siguientes de probar la velocidad de CPU de los servidores. Si no producen resultados comparables, el problema está fuera de SQL Server. Podría ser una diferencia de plan de energía, menos CPU, problema de software de máquina virtual o diferencia de velocidad del reloj.

    • Ejecute el siguiente script de PowerShell en ambos servidores y compare las salidas.

      $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"
      
    • Ejecute el siguiente código de Transact-SQL en ambos servidores y compare las salidas.

      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
      

Diagnóstico de esperas o cuellos de botella

Para optimizar una consulta que espera cuellos de botella, identifique cuánto tiempo es la espera y dónde está el cuello de botella (el tipo de espera). Una vez confirmado el tipo de espera , reduzca el tiempo de espera o elimine la espera por completo.

Para calcular el tiempo de espera aproximado, reste el tiempo de CPU (tiempo de trabajo) del tiempo transcurrido de una consulta. Normalmente, el tiempo de CPU es el tiempo de ejecución real y la parte restante de la duración de la consulta está esperando.

Ejemplos de cómo calcular la duración aproximada de la espera:

Tiempo transcurrido (ms) Tiempo de CPU (ms) Tiempo de espera (ms)
3200 3000 200
7080 1000 6080

Identificar el cuello de botella o la espera

  • Para identificar consultas históricas de larga espera (por ejemplo, >el 20 % del tiempo total transcurrido es tiempo de espera), ejecute la consulta siguiente. Esta consulta usa estadísticas de rendimiento para los planes de consulta almacenados en caché desde el inicio de 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
    
  • Para identificar las consultas que se ejecutan actualmente con esperas superiores a 500 ms, ejecute la consulta siguiente:

    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
    
  • Si puede recopilar un plan de consulta, compruebe waitstats de las propiedades del plan de ejecución en SSMS:

    1. Ejecute la consulta con Incluir plan de ejecución real activado.
    2. Haga clic con el botón derecho en el operador de la izquierda en la pestaña Plan de ejecución.
    3. Seleccione Propiedades y, a continuación, la propiedad WaitStats .
    4. Compruebe WaitTimeMs y WaitType.
  • Si está familiarizado con los escenarios PSSDiag/SQLdiag o SQL LogScout LightPerf/GeneralPerf, considere la posibilidad de usar cualquiera de ellos para recopilar estadísticas de rendimiento e identificar consultas en espera en la instancia de SQL Server. Puede importar los archivos de datos recopilados y analizar los datos de rendimiento con SQL Nexus.

Referencias para ayudar a eliminar o reducir las esperas

Las causas y las resoluciones de cada tipo de espera varían. No hay ningún método general para resolver todos los tipos de espera. Estos son los artículos para solucionar problemas comunes de tipo de espera:

Para obtener descripciones de muchos tipos de espera y lo que indican, vea la tabla en Tipos de esperas.

Diagnóstico de diferencias en el plan de consulta

Estas son algunas causas comunes de las diferencias en los planes de consulta:

  • Diferencias de tamaño de datos o valores de datos

    ¿Se usa la misma base de datos en ambos servidores, con la misma copia de seguridad de base de datos? ¿Se han modificado los datos en un servidor en comparación con el otro? Las diferencias de datos pueden dar lugar a diferentes planes de consulta. Por ejemplo, combinar la tabla T1 (1000 filas) con la tabla T2 (2000 000 filas) es diferente de combinar la tabla T1 (100 filas) con la tabla T2 (2000 000 filas). El tipo y la velocidad de la JOIN operación pueden ser significativamente diferentes.

  • Diferencias de estadísticas

    ¿Se han actualizado las estadísticas en una base de datos y no en la otra? ¿Se han actualizado las estadísticas con una frecuencia de muestreo diferente (por ejemplo, un 30 % frente a un examen completo del 100 %)? Asegúrese de actualizar las estadísticas en ambos lados con la misma frecuencia de muestreo.

  • Diferencias de nivel de compatibilidad de bases de datos

    Compruebe si los niveles de compatibilidad de las bases de datos son diferentes entre los dos servidores. Para obtener el nivel de compatibilidad de la base de datos, ejecute la consulta siguiente:

    SELECT name, compatibility_level
    FROM sys.databases
    WHERE name = '<YourDatabase>'
    
  • Diferencias de versión y compilación del servidor

    ¿Las versiones o compilaciones de SQL Server son diferentes entre los dos servidores? Por ejemplo, ¿un servidor SQL Server versión 2014 y el otro SQL Server versión 2016? Puede haber cambios en el producto que pueden dar lugar a cambios en la forma en que se selecciona un plan de consulta. Asegúrese de comparar la misma versión y compilación de SQL Server.

    SELECT ServerProperty('ProductVersion')
    
  • Diferencias de versión del Estimador de cardinalidad (CE)

    Compruebe si el estimador de cardinalidad heredado está activado en el nivel de base de datos. Para obtener más información sobre CE, vea Estimación de cardinalidad (SQL Server).

    SELECT name, value, is_value_default
    FROM sys.database_scoped_configurations
    WHERE name = 'LEGACY_CARDINALITY_ESTIMATION'
    
  • Revisiones del optimizador habilitadas o deshabilitadas

    Si las revisiones del optimizador de consultas están habilitadas en un servidor pero deshabilitadas en el otro, se pueden generar planes de consulta diferentes. Para obtener más información, vea SQL Server modelo de mantenimiento de la marca de seguimiento de revisiones 4199 del optimizador de consultas.

    Para obtener el estado de las revisiones del optimizador de consultas, ejecute la consulta siguiente:

    -- 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'
    
  • Diferencias de marcas de seguimiento

    Algunas marcas de seguimiento afectan a la selección del plan de consulta. Compruebe si hay marcas de seguimiento habilitadas en un servidor que no están habilitadas en el otro. Ejecute la consulta siguiente en ambos servidores y compare los resultados:

    -- Check at server level for trace flags
    DBCC TRACESTATUS (-1)
    
  • Diferencias de hardware (recuento de CPU, tamaño de memoria)

    Para obtener la información de hardware, ejecute la consulta siguiente:

    SELECT cpu_count, physical_memory_kb/1024/1024 PhysicalMemory_GB 
    FROM sys.dm_os_sys_info
    
  • Diferencias de hardware según el optimizador de consultas

    Compruebe el OptimizerHardwareDependentProperties de un plan de consulta y compruebe si las diferencias de hardware se consideran significativas para los distintos planes.

    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>%'
    
  • Tiempo de espera del optimizador

    ¿Hay un problema de tiempo de espera del optimizador ? El optimizador de consultas puede dejar de evaluar las opciones del plan si la consulta que se ejecuta es demasiado compleja. Cuando se detiene, elige el plan con el costo más bajo disponible en ese momento. Esto puede dar lugar a lo que parece una elección de plan arbitraria en un servidor frente a otro.

  • Opciones set

    Algunas opciones SET afectan al plan, como SET ARITHABORT. Para obtener más información, vea Opciones de SET.

  • Diferencias de sugerencias de consulta

    ¿Una consulta usa sugerencias de consulta y la otra no? Compruebe manualmente el texto de la consulta para establecer la presencia de sugerencias de consulta.

  • Planes que distinguen parámetros (problema de examen de parámetros)

    ¿Está probando la consulta con exactamente los mismos valores de parámetro? Si no es así, puede empezar allí. ¿Se compiló el plan anteriormente en un servidor en función de un valor de parámetro diferente? Pruebe las dos consultas mediante la sugerencia de consulta RECOMPILE para asegurarse de que no se produzca ninguna reutilización del plan. Para obtener más información, vea Investigar y resolver problemas confidenciales de parámetros.

  • Opciones de base de datos diferentes o opciones de configuración con ámbito

    ¿Se usan las mismas opciones de base de datos o opciones de configuración con ámbito en ambos servidores? Algunas opciones de base de datos pueden influir en las opciones del plan. Por ejemplo, compatibilidad de bases de datos, CE heredada frente a CE predeterminada y examen de parámetros. Ejecute la siguiente consulta desde un servidor para comparar las opciones de base de datos usadas en los dos servidores:

    -- 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
    
  • Guías de plan

    ¿Se usan guías de plan para las consultas en un servidor, pero no en el otro? Ejecute la consulta siguiente para establecer diferencias:

    SELECT * FROM sys.plan_guides