Auf einem SQL Server 2016 SP2 mit maximal 25 GB Arbeitsspeicher haben wir eine Abfrage, die ungefähr 80 Mal in einer Minute ausgeführt wird. Die Abfrage verschüttet ungefähr 4000 Seiten in Tempdb. Dies verursacht eine Menge IO auf der Festplatte von Tempdb.
Wenn Sie sich den Abfrageplan ansehen (vereinfachte Abfrage), werden Sie feststellen, dass die Anzahl der geschätzten Zeilen der Anzahl der tatsächlichen Zeilen entspricht, dass jedoch noch Verschüttungen auftreten. Veraltete Statistiken können also nicht die Ursache des Problems sein.
Ich habe einige Tests durchgeführt und folgende Query-Spills an Tempdb vorgenommen:
select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Wenn ich jedoch eine andere Spalte auswähle, treten keine Verschmutzungen auf:
select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Also habe ich versucht, die Größe der ID-Spalte zu "vergrößern":
select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Dann tritt auch kein Verschütten auf.
Warum wird der eindeutige Bezeichner nicht auf Tempdb und eine Datums- / Uhrzeitspalte übertragen? Wenn ich ungefähr 20000 Datensätze lösche, passiert auch kein Verschütten, wenn ich die ID-Spalte auswähle.
Mit folgendem Skript können Sie das Problem reproduzieren:
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])