Classifique derramamentos para tempdb, mas as linhas estimadas são iguais às linhas reais

14

Em um SQL Server 2016 SP2 com memória máxima definida como 25 GB, temos uma consulta que é executada cerca de 80 vezes em um minuto. A consulta derrama aproximadamente 4000 páginas no tempdb. Isso causa muitas E / S no disco do tempdb.

Ao examinar o plano de consulta (consulta simplificada), você verá que o número estimado de linhas é igual ao número real de linhas, mas ainda ocorrem derramamentos. Portanto, estatísticas desatualizadas não podem ser a causa do problema.

Fiz alguns testes e os seguintes derramamentos de consulta no Tempdb:

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

Mas se eu selecionar uma coluna diferente, nenhum derramamento ocorrerá:

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

Então, eu tentei 'aumentar' o tamanho da coluna id:

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

Também não ocorre derramamento.

Por que o identificador exclusivo está se espalhando para tempdb e uma coluna de data e hora não? Quando eu excluo cerca de 20000 registros, também não ocorre derramamento quando seleciono a coluna de identificação.

Com o seguinte script, você pode reproduzir o 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]) 
Frederik Vanderhaegen
fonte

Respostas:

14

Ative o sinalizador de rastreamento 7470.

CORRECÇÃO: O operador de classificação derrama para tempdb no SQL Server 2012 ou no SQL Server 2014 quando o número estimado de linhas e o tamanho da linha estão corretos

Como escrevi em resposta à pergunta do Plano de consulta :

Esse sinalizador de rastreamento corrige uma supervisão no cálculo. É bastante seguro de usar e, na minha opinião, deve estar ativado por padrão. A alteração é protegida por um sinalizador de rastreamento, simplesmente para evitar alterações inesperadas no plano.

Paul White 9
fonte