Questo è un bug in SQL Server (dal 2008 al 2014 incluso).
La mia segnalazione di bug è qui .
La condizione di filtro viene inserita nell'operatore di scansione come predicato residuo, ma la memoria concessa per l'ordinamento viene calcolata erroneamente in base alla stima di cardinalità pre-filtro .
Per illustrare il problema, possiamo usare il flag di traccia 9130 (non documentato e non supportato) per impedire che il filtro venga spinto verso il basso nell'operatore di scansione . La memoria concessa all'ordinamento ora è correttamente basata sulla cardinalità stimata dell'output del filtro, non sulla scansione:
SELECT
T.TID,
T.FilterMe,
T.SortMe,
T.Unused
FROM dbo.Test AS T
WHERE
T.FilterMe = 567
ORDER BY
T.SortMe
OPTION (QUERYTRACEON 9130); -- Not for production systems!
Per un sistema di produzione , sarà necessario adottare delle misure per evitare la forma problematica del piano (un filtro inserito in una scansione con un ordinamento su un'altra colonna). Un modo per farlo è fornire un indice sulla condizione del filtro e / o fornire l'ordinamento richiesto.
-- Index on the filter condition only
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe
ON dbo.Test (FilterMe);
Con questo indice in atto, la concessione di memoria desiderata per l'ordinamento è solo 928 KB :
Andando oltre, il seguente indice può evitare completamente l'ordinamento ( zero memory grant):
-- Provides filtering and sort order
-- nvarchar(max) column deliberately not INCLUDEd
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe_SortMe
ON dbo.Test (FilterMe, SortMe);
Testato e bug confermato sulle seguenti build di SQL Server x64 Developer Edition:
2014 : 12.00.2430 (RTM CU4)
2012 : 11.00.5556 (SP2 CU3)
2008R2 : 10.50.6000 (SP3)
2008 : 10.00.6000 (SP4)
Questo problema è stato risolto in SQL Server 2016 Service Pack 1 . Le note di rilascio includono quanto segue:
Numero di bug VSTS 8024987
Le scansioni della tabella e le scansioni dell'indice con predicato push down tendono a sovrastimare la concessione di memoria per l'operatore principale.
Testato e confermato risolto su:
Microsoft SQL Server 2016 (SP1) - 13.0.4001.0 (X64) Developer Edition
Microsoft SQL Server 2014 (SP2-CU3) 12.0.5538.0 (X64) Developer Edition
Entrambi i modelli CE.