Sur un SQL Server 2016 SP2 avec une mémoire maximale définie sur 25 Go, nous avons une requête qui s'exécute environ 80 fois en une minute. La requête renverse environ 4000 pages à tempdb. Cela provoque beaucoup d'E / S sur le disque de tempdb.
Lorsque vous jetez un œil au plan de requête (requête simplifiée), vous verrez que le nombre de lignes estimées est égal au nombre de lignes réelles mais que des déversements se produisent toujours. Les statistiques obsolètes ne peuvent donc pas être la cause du problème.
J'ai fait quelques tests et suivi des déversements de requêtes vers Tempdb:
select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Mais si je sélectionne une autre colonne, aucun déversement ne se produit:
select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
J'ai donc essayé d'agrandir la taille de la colonne id:
select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Ensuite, aucun déversement ne se produit.
Pourquoi l'identificateur unique se répand-il dans tempdb et dans une colonne datatime? Lorsque je supprime environ 20000 enregistrements, aucun déversement ne se produit également lorsque je sélectionne la colonne id.
Avec le script suivant, vous pouvez reproduire le problème:
CREATE TABLE SortProblem
(
id UNIQUEIDENTIFIER,
startdate DATETIME,
sequencenumber BIGINT,
status VARCHAR(50),
PRIMARY KEY CLUSTERED(id)
)
SET nocount ON;
WITH nums(num)
AS (SELECT TOP 103000 ROW_NUMBER()
OVER (
ORDER BY 1/0)
FROM sys.all_objects o1,
sys.all_objects o2)
INSERT INTO SortProblem
SELECT newid(),
DATEADD(millisecond, num, GETDATE()),
num,
CASE
WHEN num <= 100000 THEN 'A'
WHEN num <= 101000 THEN 'B'
WHEN num <= 102000 THEN 'C'
WHEN num <= 103000 THEN 'D'
END
FROM nums
CREATE NONCLUSTERED INDEX [IX_Status]
ON [dbo].[SortProblem]([status] ASC)
INCLUDE ([sequencenumber])