Оператор использовал базу данных tempdb для разлива данных во время выполнения с уровнем разлива 2

16

Я изо всех сил пытаюсь минимизировать стоимость операции сортировки в плане запроса с предупреждением Operator usedtempdbto spill data during execution with spill level 2

Я обнаружил несколько сообщений, связанных с данными о разливах во время выполнения с уровнем разлива 1 , но не с уровнем 2. Кажется , что уровень 1 вызван устаревшей статистикой , что насчет уровня 2? Я не мог найти ничего, связанного с level 2.

Я нашел эту статью очень интересной, связанной с сортировкой предупреждений:

Никогда не игнорируйте предупреждение о сортировке в SQL Server

Мой сервер Sql?

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) 17 июня 2016 г. 19:14:09 Авторское право (c) Выпуск Microsoft Corporation Enterprise (64-разрядный) для Windows NT 6.3 (сборка 9600:) (гипервизор)

Мое оборудование?

запустив приведенный ниже запрос для поиска оборудования:

- Информация об оборудовании из SQL Server 2012

SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio],
cpu_count/hyperthread_ratio AS [Physical CPU Count], 
physical_memory_kb/1024 AS [Physical Memory (MB)], affinity_type_desc, 
virtual_machine_type_desc, sqlserver_start_time
FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);

введите описание изображения здесь

в настоящее время выделенная память

SELECT
(physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB,
(locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB,
(total_virtual_address_space_kb/1024) AS Total_VAS_in_MB,
process_physical_memory_low,
process_virtual_memory_low
FROM sys.dm_os_process_memory;

введите описание изображения здесь

когда я выполняю свой запрос с объемом в один год, я не получаю никаких предупреждений, как показано на рисунке ниже:

введите описание изображения здесь

Но когда я запускаю его только на 1 день, я получаю это предупреждение on the sort operator:

введите описание изображения здесь

это запрос:

    DECLARE @FromDate SMALLDATETIME = '19-OCT-2016 11:00'
    DECLARE @ToDate   SMALLDATETIME = '20-OCT-2016 12:00'




    SELECT      DISTINCT
                a.strAccountCode ,
                a.strAddressLine6 ,
                a.strPostalCode ,
                CASE    WHEN a.strCountryCode IN ('91','92') THEN 'GB-Int'
                        ELSE a.strCountryCode
                        END AS [strCountryCode]
    FROM        Bocss2.dbo.tblBAccountParticipant AS ap
    INNER JOIN  Bocss2.dbo.tblBAccountParticipantAddress AS apa ON ap.lngParticipantID = apa.lngParticipantID
                                                                AND apa.sintAddressTypeID = 2
    INNER JOIN  Bocss2.dbo.tblBAccountHolder AS ah ON ap.lngParticipantID = ah.lngParticipantID
    INNER JOIN  Bocss2.dbo.tblBAddress AS a ON apa.lngAddressID = a.lngAddressID
                                            AND a.blnIsCurrent = 1
    INNER JOIN  Bocss2.dbo.tblBOrder AS o ON ap.lngParticipantID = o.lngAccountParticipantID
                                        AND o.sdtmOrdCreated >= @FromDate
                                        AND o.sdtmOrdCreated < @ToDate

OPTION(RECOMPILE)

план запроса здесь

план запроса с использованием pastetheplan

Вопросы: 1) в плане запросов я вижу это:

StatementOptmEarlyAbortReason="GoodEnoughPlanFound" CardinalityEstimationModelVersion="70" 

почему 70? Я использую SQL Server 2014

2) как мне избавиться от этого оператора сортировки (если это вообще возможно)?

3) Я ожидал, что ожидаемый срок службы страницы будет довольно низким, если не считать добавления памяти на этот сервер. Могу ли я взглянуть на что-нибудь еще, чтобы увидеть, смогу ли я предотвратить это предупреждение?

ура

Обновление после ответа от Шанки и Пола Уайта

Я проверил мою статистику в соответствии со сценарием ниже, и они кажутся все правильными и обновленными

это все индексы и таблицы, используемые в этом запросе.

DBCC SHOW_STATISTICS ('dbo.tblBAddress','IDXF_tblBAddress_lngAddressID__INC')
GO
DBCC SHOW_STATISTICS  ('dbo.tblBOrder','IX_tblBOrder_sdtmOrdCreated_INCL')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountHolder','PK_tblAccountHolder')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipant','PK_tblBAccountParticipants')
GO
DBCC SHOW_STATISTICS ('dbo.tblBAccountParticipantAddress','IDXF_tblBAccountParticipantAddress_lngParticipantID')
GO

вот что мне вернули:

введите описание изображения здесь

введите описание изображения здесь

Это частичный результат, но я снова посетил их все.

Для обновления статистики у меня есть Ola Hallengren.

задание оптимизации индекса - запуск по расписанию один раз в неделю - воскресенье

EXECUTE [dbo].[IndexOptimize] 
@Databases = 'USER_DATABASES,-%Archive', 
@Indexes = 'ALL_INDEXES' , 
@FragmentationLow = NULL,
@FragmentationMedium = NULL,
@FragmentationHigh = NULL,
@PageCountLevel=1000,
@StatisticsSample =100
,@UpdateStatistics = 'Index', 
@OnlyModifiedStatistics = 'Y',
@TimeLimit=10800, 
@LogToTable = 'Y'

Хотя статистика, похоже, обновилась После того, как я запустил следующий скрипт, я больше не получал предупреждения об операторе сортировки.

UPDATE STATISTICS [Bocss2].[dbo].[tblBOrder]  WITH FULLSCAN
--1 hour  04 min 14 sec

UPDATE STATISTICS [Bocss2].[dbo].tblBAddress  WITH FULLSCAN
-- 45 min 29 sec

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountHolder WITH FULLSCAN
-- 26 SEC

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipant WITH FULLSCAN
-- 4 min

UPDATE STATISTICS  [Bocss2].[dbo].tblBAccountParticipantAddress WITH FULLSCAN
-- 7 min 3 sec
Марчелло Миорелли
источник
На сколько сократилось время запроса?
влиятельный
Я никогда не мог реализовать решение, которое позволило бы мне обновлять статистику для таких больших таблиц. Решение состоит в том, чтобы разделить таблицы и использовать статистику incrementao, но я никогда не подходил, чтобы реализовать это, потому что я оставил этого работодателя. Что-то, что я хотел бы реализовать, хотя.
Марчелло Миорелли

Ответы:

17

что насчет 2 уровня? Я не смог найти ничего, связанного с уровнем 2.

Согласно этому старому документу MS, число в разливе Tempdb указывает, сколько проходов требуется для данных для сортировки данных. Итак, Spill 1 означает, что для сортировки данных должно пройти 1 раз, а 2 - 2 раза.

Цитата из блога:

Если запрос, включающий операцию сортировки, генерирует класс событий Sort Warnings со значением уровня пролива 2, это может повлиять на производительность запроса, поскольку для сортировки данных требуется несколько проходов по данным. В приведенном ниже примере мы видим значение уровня разлива 1, означающее, что для завершения сортировки достаточно одного прохода по данным.

почему 70? Я использую SQL Server 2014

Это связано с тем, что уровень совместимости базы данных на рисунке НЕ равен 120 (что означает уровень совместимости базы данных 2014 года), поскольку это не 120 запросов, которые будут обрабатываться с использованием старой модели оценки мощности (CE), которая называется CardinalityEstimationModelVersion="70". Я уверен, что вы знаете, что с SQL Server 2014 у нас есть новый CE.

как мне избавиться от этого оператора сортировки (если это вообще возможно)?

Отдельная команда, которую вы используете, вызывает операцию сортировки. Сортируемые данные не помещаются в память, поэтому они помещаются в базу данных tempdb, и когда это происходит, в плане выполнения выдается предупреждение о сортировке с желтым восклицательным знаком. Сортировать предупреждения не всегда проблема.

В плане выполнения видно, что предполагаемое количество сортируемых строк равно 1, но во время выполнения встречается 16 353. Объем памяти, зарезервированный для сортировки, основан на ожидаемом (предполагаемом) размере ввода и не может увеличиваться во время выполнения (в этом случае).

Небольшое выделение памяти для запроса (1632 КБ) также распределяется между параллельно выполняющимися операторами, занимающими память (операции сортировки и «оптимизированные» циклы). В вашем плане это означает, что 33,33% (544 КБ) доступно для сортировки при чтении строк (доля входной памяти). Недостаточно памяти для сортировки 16 353 строк, поэтому она выливается в базу данных tempdb . Одного уровня разлива недостаточно для завершения сортировки, поэтому необходим второй уровень разлива (см. Ссылку в конце для получения более подробной информации об уровнях разлива).

Сортировать свойства

Сортировка свойств, как показано в SQL Sentry Plan Explorer

Обновление статистики, вероятно, поможет с оценкой количества элементов. Возможно, вы столкнулись с проблемой восходящего ключа, особенно на столе tblBOrder. Простой выбор из этой таблицы с буквальными датами из вашего вопроса, скорее всего, оценит одну строку прямо сейчас.

Я ожидал, что срок службы страницы будет довольно низким, кроме добавления дополнительной памяти к этому серверу, есть ли еще что-то, на что я могу взглянуть, чтобы увидеть, могу ли я предотвратить это предупреждение?

PLE - это показатель активности ввода / вывода, увеличился ли он? Так происходит ли это часто или только когда вы выполняете определенный запрос, или это произошло только сегодня. Избегайте реакции коленного рефлекса, во-первых, мы должны убедиться, что вы действительно сталкиваетесь с нехваткой памяти, или какой-то мошеннический запрос, который генерирует слишком много операций ввода-вывода, вызывает это. В любом случае у вас уже есть память 97 G, выделенная для SQL Server.

Для получения дополнительной информации об уровнях разлива и восходящей ключевой проблеме см .:

Shanky
источник