Ordinamento degli sversamenti in tempdb ma le righe stimate equivalgono alle righe effettive


14

Su un SQL Server 2016 SP2 con una memoria massima impostata su 25 GB abbiamo una query che viene eseguita circa 80 volte in un minuto. La query si estende su circa 4000 pagine in tempdb. Ciò causa molti IO sul disco di tempdb.

Quando dai un'occhiata al piano di query (query semplificata) noterai che il numero di righe stimate è uguale al numero di righe effettive ma si verificano comunque sversamenti. Quindi statistiche obsolete non possono essere la causa del problema.

Ho fatto alcuni test e le seguenti query si riversano su Tempdb:

select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)

Ma se seleziono una colonna diversa non si verificano perdite:

select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc 
option (maxdop 1)

Quindi ho cercato di 'ingrandire' la dimensione della colonna id:

select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc 
option (maxdop 1)

Quindi anche non si verificano fuoriuscite.

Perché l'identificatore univoco si sta riversando su tempdb e su una colonna del datatime no? Quando elimino circa 20000 record, anche quando si seleziona la colonna ID non si verifica alcun versamento.

Con il seguente script è possibile riprodurre il problema:

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]) 

Risposte:


14

Abilita flag di traccia 7470.

FIX: l'operatore di ordinamento si riversa su tempdb in SQL Server 2012 o SQL Server 2014 quando il numero stimato di righe e le dimensioni delle righe sono corrette

Come ho scritto in risposta alla domanda del piano di query :

Questo flag di traccia corregge una svista nel calcolo. È abbastanza sicuro da usare, e secondo me dovrebbe essere attivo di default. La modifica è protetta da un flag di traccia semplicemente per evitare cambiamenti imprevisti del piano.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.