Estoy luchando por minimizar el costo de la operación de clasificación en un plan de consulta con la advertencia Operator used
tempdbto 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);
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;
Cuando ejecuto mi consulta con un año de alcance, no recibo ninguna advertencia, según la imagen a continuación:
Pero cuando lo ejecuto solo durante 1 día, recibo esta advertencia on the sort operator
:
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 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:
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