Verschüttetes in Tempdb sortieren, aber geschätzte Zeilen entsprechen den tatsächlichen Zeilen

14

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]) 
Frederik Vanderhaegen
quelle

Antworten:

14

Aktivieren Sie das Ablaufverfolgungsflag 7470.

UPDATE: Sortieroperator wird in SQL Server 2012 oder SQL Server 2014 in Tempdb verschoben, wenn die geschätzte Anzahl der Zeilen und die Zeilengröße korrekt sind

Wie ich als Antwort auf die Frage zum Abfrageplan schrieb :

Dieses Trace-Flag korrigiert ein Versehen in der Berechnung. Die Verwendung ist ziemlich sicher und sollte meiner Meinung nach standardmäßig aktiviert sein. Die Änderung wird durch ein Ablaufverfolgungsflag geschützt, um unerwartete Planänderungen zu vermeiden.

Paul White Monica wieder einsetzen
quelle