Сортувати розливи до tempdb, але орієнтовні рядки дорівнюють фактичним рядкам


14

На SQL Server 2016 SP2 з максимальною пам’яттю 25 ГБ є запит, який виконується приблизно 80 разів за хвилину. Запит розсипає близько 4000 сторінок до tempdb. Це спричиняє багато IO на диску tempdb.

Якщо ви подивитесь на план запитів (спрощений запит), ви побачите, що кількість оцінених рядків дорівнює кількості фактичних рядків, але все-таки відбувається розлив. Тож застаріла статистика не може бути причиною проблеми.

Я зробив кілька тестувань та наступних розливів запитів до Tempdb:

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

Але якщо я виберу інший стовпець, розливи не трапляються:

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

Тому я спробував «збільшити» розмір стовпця id:

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

Тоді також не відбувається розливу.

Чому унікальний ідентифікатор розливається до tempdb та стовпця часу даних? Коли я видаляю близько 20000 записів, тоді також не відбувається розливу, коли я вибираю стовпчик id.

За допомогою наступного сценарію ви можете відтворити проблему:

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

Відповіді:


14

Увімкнути прапор сліду 7470.

ВИПРАВЛЕННЯ: Сортування розливу оператора до tempdb в SQL Server 2012 або SQL Server 2014, коли орієнтовна кількість рядків та розмір рядків є правильними

Як я писав у відповідь на запитання щодо плану запитів :

Цей прапор слідів виправляє недогляд у розрахунку. Він досить безпечний у використанні, і, на мою думку, він повинен бути включений за замовчуванням. Зміна захищена прапором сліду просто, щоб уникнути несподіваних змін плану.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.