Ceci est un bogue dans SQL Server (de 2008 à 2014 inclus).
Mon rapport de bogue est ici .
La condition de filtrage est abaissée dans l'opérateur d'analyse en tant que prédicat résiduel, mais la mémoire allouée pour le tri est calculée de manière erronée sur la base de l' estimation de cardinalité avant filtrage .
Pour illustrer le problème, nous pouvons utiliser l' indicateur de trace 9130 (non documenté et non pris en charge) pour empêcher que le filtre ne soit enfoncé dans l' opérateur d' analyse . La mémoire attribuée au tri est maintenant correctement basée sur la cardinalité estimée de la sortie du filtre, et non sur l'analyse:
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!
Pour un système de production , il faudra prendre des mesures pour éviter la forme de plan problématique (un filtre inséré dans une analyse avec une sorte sur une autre colonne). Une façon de procéder consiste à fournir un index sur la condition de filtre et / ou à fournir l'ordre de tri requis.
-- Index on the filter condition only
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe
ON dbo.Test (FilterMe);
Avec cet index en place, l’allocation de mémoire souhaitée pour le tri n’est que de 928 Ko :
En allant plus loin, l'index suivant peut éviter complètement le tri ( allocation mémoire nulle ):
-- Provides filtering and sort order
-- nvarchar(max) column deliberately not INCLUDEd
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe_SortMe
ON dbo.Test (FilterMe, SortMe);
Testé et confirmé sur les versions suivantes de 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)
Ce problème a été résolu dans SQL Server 2016 Service Pack 1 . Les notes de publication incluent les éléments suivants:
Numéro de bogue VSTS 8024987 Les
analyses de table et les analyses d'index avec prédicat «enfoncé vers le bas» ont tendance à surestimer l'allocation de mémoire pour l'opérateur parent.
Testé et confirmé fixé sur:
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
Les deux modèles CE.