El operador usó tempdb para derramar datos durante la ejecución con nivel de derrame 2


16

Estoy luchando por minimizar el costo de la operación de clasificación en un plan de consulta con la advertencia Operator usedtempdbto spill data during execution with spill level 2

He encontrado varias publicaciones relacionadas con los datos de derrames durante la ejecución con el nivel de derrame 1 , pero no el nivel 2. El nivel 1 parece ser causado por estadísticas desactualizadas , ¿qué pasa con el nivel 2? No pude encontrar nada relacionado con level 2.

Este artículo me pareció muy interesante en relación con las advertencias de clasificación:

Nunca ignore una advertencia de clasificación en SQL Server

Mi servidor SQL?

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) 17 de junio de 2016 19:14:09 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) en Windows NT 6.3 (Build 9600:) (Hypervisor)

Mi hardware

ejecutando la consulta a continuación para encontrar el hardware:

- Información de hardware de SQL Server 2012

SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio],
cpu_count/hyperthread_ratio AS [Physical CPU Count], 
physical_memory_kb/1024 AS [Physical Memory (MB)], affinity_type_desc, 
virtual_machine_type_desc, sqlserver_start_time
FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);

ingrese la descripción de la imagen aquí

memoria asignada actualmente

SELECT
(physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB,
(locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB,
(total_virtual_address_space_kb/1024) AS Total_VAS_in_MB,
process_physical_memory_low,
process_virtual_memory_low
FROM sys.dm_os_process_memory;

ingrese la descripción de la imagen aquí

Cuando ejecuto mi consulta con un año de alcance, no recibo ninguna advertencia, según la imagen a continuación:

ingrese la descripción de la imagen aquí

Pero cuando lo ejecuto solo durante 1 día, recibo esta advertencia on the sort operator:

ingrese la descripción de la imagen aquí

Esta es la consulta:

    DECLARE @FromDate SMALLDATETIME = '19-OCT-2016 11:00'
    DECLARE @ToDate   SMALLDATETIME = '20-OCT-2016 12:00'




    SELECT      DISTINCT
                a.strAccountCode ,
                a.strAddressLine6 ,
                a.strPostalCode ,
                CASE    WHEN a.strCountryCode IN ('91','92') THEN 'GB-Int'
                        ELSE a.strCountryCode
                        END AS [strCountryCode]
    FROM        Bocss2.dbo.tblBAccountParticipant AS ap
    INNER JOIN  Bocss2.dbo.tblBAccountParticipantAddress AS apa ON ap.lngParticipantID = apa.lngParticipantID
                                                                AND apa.sintAddressTypeID = 2
    INNER JOIN  Bocss2.dbo.tblBAccountHolder AS ah ON ap.lngParticipantID = ah.lngParticipantID
    INNER JOIN  Bocss2.dbo.tblBAddress AS a ON apa.lngAddressID = a.lngAddressID
                                            AND a.blnIsCurrent = 1
    INNER JOIN  Bocss2.dbo.tblBOrder AS o ON ap.lngParticipantID = o.lngAccountParticipantID
                                        AND o.sdtmOrdCreated >= @FromDate
                                        AND o.sdtmOrdCreated < @ToDate

OPTION(RECOMPILE)

el plan de consulta está aquí

el plan de consulta usando pastetheplan

Preguntas: 1) en el plan de consulta veo esto:

StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="70" 

¿Por qué 70? Estoy usando el servidor sql 2014

2) ¿cómo me deshago de ese operador de clasificación (si es posible)?

3) He visto que la expectativa de vida de la página es bastante baja, además de agregar más memoria a este servidor, ¿hay algo más que pueda ver para ver si puedo evitar esta advertencia?

salud

Actualización después de la respuesta de Shanky y Paul White

Verifiqué mis estadísticas de acuerdo con el siguiente script, y parecen todas correctas y actualizadas.

Estos son todos los índices y tablas utilizados en esta consulta.

DBCC SHOW_STATISTICS ('dbo.tblBAddress','IDXF_tblBAddress_lngAddressID__INC')
GO
DBCC SHOW_STATISTICS  ('dbo.tblBOrder','IX_tblBOrder_sdtmOrdCreated_INCL')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountHolder','PK_tblAccountHolder')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipant','PK_tblBAccountParticipants')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipantAddress','IDXF_tblBAccountParticipantAddress_lngParticipantID')
GO

esto es lo que me devolvieron:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Este es un resultado parcial, pero los he vuelto a visitar a todos.

Para la actualización de estadísticas actualmente tengo Ola Hallengren

the Index Optimize Job - programado para ejecutarse una vez a la semana - domingos

EXECUTE [dbo].[IndexOptimize] 
@Databases = 'USER_DATABASES,-%Archive', 
@Indexes = 'ALL_INDEXES' , 
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@PageCountLevel=1000,
@StatisticsSample =100
,@UpdateStatistics = 'Index', 
@OnlyModifiedStatistics = 'Y',
@TimeLimit=10800, 
@LogToTable = 'Y'

Aunque las estadísticas parecían estar actualizadas Después de ejecutar el siguiente script, no recibí más advertencias sobre el operador de clasificación.

UPDATE STATISTICS [Bocss2].[dbo].[tblBOrder]  WITH FULLSCAN
--1 hour  04 min 14 sec

UPDATE STATISTICS [Bocss2].[dbo].tblBAddress  WITH FULLSCAN
-- 45 min 29 sec

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountHolder WITH FULLSCAN
-- 26 SEC

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipant WITH FULLSCAN
-- 4 min

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipantAddress WITH FULLSCAN
-- 7 min 3 sec

¿Cuánto se redujo el tiempo de consulta?
influyente

Nunca podría implementar una solución que me permitiera mantener las estadísticas actualizadas en tablas tan grandes. La solución sería dividir las tablas y usar estadísticas increo, pero nunca bajé a implementarlo porque dejé a ese empleador. Sin embargo, algo que me gustaría haber implementado.
Marcello Miorelli

Respuestas:


17

¿Qué pasa con el nivel 2? No pude encontrar nada relacionado con el nivel 2.

Según este viejo documento de MS, el número en el derrame de Tempdb significa cuántos pases se requieren sobre los datos para ordenarlos. Entonces, el Derrame 1 significa que tiene que pasar 1 vez para ordenar los datos y 2 significa que tiene que pasar 2 veces.

Citando del blog:

Si una consulta que involucra una operación de clasificación genera una clase de evento de Advertencias de clasificación con un valor de nivel de derrame de 2, el rendimiento de la consulta puede verse afectado porque se requieren múltiples pases sobre los datos para clasificar los datos. En el siguiente ejemplo, vemos un valor de nivel de derrame de 1, lo que significa que una pasada sobre los datos fue suficiente para completar el ordenamiento.

¿Por qué 70? Estoy usando el servidor sql 2014

Esto se debe a que el nivel de compatibilidad de la base de datos en la imagen NO es 120 (lo que significa el nivel de compatibilidad de la base de datos 2014) ya que no es 120, la consulta se procesará utilizando el antiguo modelo de estimación de cardinalidad (CE) que se conoce como CardinalityEstimationModelVersion="70". Estoy seguro de que sabe que desde SQL Server 2014 tenemos un nuevo CE.

¿Cómo me deshago de ese operador de clasificación (si es posible)?

El comando distinto que está utilizando está causando la operación de clasificación. Los datos que se están ordenando no caben en la memoria, por lo que se derraman a tempdb y, cuando esto sucede, se da una advertencia de clasificación con un signo de exclamación amarillo en el plan de ejecución. Las advertencias de clasificación no siempre son un problema.

Puede ver en el plan de ejecución que el número estimado de filas a ordenar es 1, pero se encuentran 16,353 en tiempo de ejecución. La cantidad de memoria reservada para la ordenación se basa en el tamaño esperado (estimado) de la entrada y no puede crecer durante la ejecución (en este caso).

La pequeña concesión de memoria para la consulta (1632 KB) también se reparte entre los operadores consumidores de memoria que se ejecutan simultáneamente (clasificación y uniones de bucle 'optimizadas' ). En su plan, eso significa que 33.33% (544KB) está disponible para la clasificación mientras lee filas (fracción de memoria de entrada). Esto no es suficiente memoria para ordenar las 16.353 filas, por lo que se derrama a tempdb . Un derrame de un solo nivel no es suficiente para completar la clasificación, por lo que se necesita un segundo nivel de derrame (consulte la referencia al final para obtener más detalles sobre los niveles de derrame).

Ordenar propiedades

Ordenar propiedades como se ve en el Explorador de planes de SQL Sentry

La actualización de las estadísticas probablemente ayudará con el problema de la estimación de la cardinalidad. Puede estar experimentando el problema de la clave ascendente, especialmente en la mesa tblBOrder. Una simple selección de esa tabla con las fechas literales de su pregunta probablemente estimará una fila en este momento.

He visto que la expectativa de vida de la página es bastante baja, además de agregar más memoria a este servidor, ¿hay alguna otra cosa que pueda ver para ver si puedo evitar esta advertencia?

PLE es indicación de la cantidad de actividad de E / S, ¿ha aumentado? Entonces, ¿esto sucede a menudo o solo cuando ejecuta cierta consulta o ha ocurrido esto hoy? Evite la reacción instintiva, primero debemos asegurarnos de que realmente se enfrenta a una presión de memoria o alguna consulta maliciosa que genera demasiada E / S está causando esto. De todos modos, ya tiene 97 G de memoria asignada a SQL Server.

Para obtener más información sobre los niveles de derrame y el problema clave ascendente, consulte:

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.