Оператор, вызывающий утечку данных в базе данных tempdb

#sql #sql-server #sqlperformance

Вопрос:

У меня есть запрос ниже, который приводит к тому, что оператор сортировки разливает данные в базе данных tempdb и, скорее всего, является причиной проблемы с производительностью, с которой я сталкиваюсь.

 SELECT 
    P_All.Status, P_All.Date, P_All.Year, P_All.Amount, P_All.ID,
    P.ID, 
    A.ID, A.Type_ID, A.Date, A.Amount,
    R.Year, R.Amount, R.Balance, R.Title, R.TOTAL, R.TYPE, R.Date, R.ID,
    O.TYPE, O.Name, O.CITY, 
    D.City, D.Code, D.Zip, D.Address,
    S.Description,
 FROM   
    Pmnt P INNER JOIN Rqst R ON P.Rqst_ID=R.ID
    INNER JOIN Org O ON R.Org_ID=O.ID
    INNER JOIN Pmnt P_All ON R.ID=P_All.Rqst_ID
    LEFT OUTER JOIN Actvty A ON R.ID=A.Rqst_ID
    INNER JOIN Addrs D ON O.Addrs_ID=D.ID
    INNER JOIN Sts S ON O.Sts_ID=Sts.ID
 WHERE
    R.TYPE=N'INITIAL' AND R.Date<{ts '2021-08-13 00:00:00'}
 ORDER BY
    O.TYPE, R.ID
 

Я попробовал несколько вещей, которые нашел в Google, но ни одна из них не помогла избавиться от этого предупреждения.

Ниже приведены вещи, которые я пробовал до сих пор:

  • Обновлена статистика с использованием Exec sp_updatestats , а также UPDATE STATISTICS Org with fullscan (для всех 6 таблиц выше).
  • Созданы индексы, включающие все столбцы, участвующие в этом запросе, для всех 6 таблиц. (Я очень новичок в индексах)

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

Примечание.Я нашел одно вероятное решение для обновления уровня совместимости БД до 150 этого в этой статье, но я боюсь, что если его изменить, это может что-то испортить. Итак, на данный момент я ищу какое-то решение, связанное с индексами или оптимизацией запроса.

Фактический план выполнения SQL — запроса- https://www.brentozar.com/pastetheplan/?id=HJxdkN4et

Комментарии:

1. Первое, что требуется для помощи в настройке, — это предоставить фактический план выполнения с помощью PasteThePlan

2. К вашему сведению, вам действительно не нужны все эти круглые скобки в вашем FROM ; они на самом деле затрудняют следование вашему SQL, а не облегчают.

3. @Stu Добавил ссылку на план в пост.

4. @Larnu Да, извини за это. Это очень старый код, написанный кем-то другим. Обновлено сейчас.

Ответ №1:

вам действительно не нужны все эти круглые скобки в вашем ОТ

На самом деле это ключ к разгадке. Это наводит на мысль, что первоначальный автор был новичком, использующим графический конструктор запросов, поэтому вы должны подозревать, что у этого запроса есть проблемы, и оказывается, что это так.

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

     <WaitStats>
      <Wait WaitType="MEMORY_ALLOCATION_EXT" WaitTimeMs="18" WaitCount="7171" />
      <Wait WaitType="RESERVED_MEMORY_ALLOCATION_EXT" WaitTimeMs="61" WaitCount="64279" />
      <Wait WaitType="SOS_SCHEDULER_YIELD" WaitTimeMs="358" WaitCount="3705" />
      <Wait WaitType="LATCH_EX" WaitTimeMs="810" WaitCount="149" />
      <Wait WaitType="IO_COMPLETION" WaitTimeMs="38588" WaitCount="10990" />
      <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="117148" WaitCount="1530" />
      <Wait WaitType="CXPACKET" WaitTimeMs="558490" WaitCount="39296" />
    </WaitStats>
    <QueryTimeStats CpuTime="54137" ElapsedTime="156188" />
 

Из 156 секунд прошедшего времени 117 секунд ожидают отправки 4,2 миллиона строк клиенту. Активность содержит всего 200 тыс. строк, а остальные таблицы небольшие, менее 100 тыс. строк.

Но это соединение между несколькими отношениями 1-много, которое увеличивает размер результата и затрудняет прогнозирование конечного размера результата (что приводит к разливу).

Так что это повод для переосмысления этого запроса. Возможно, вы можете объединить его на сервере вместо отправки всех результатов клиенту или разбить его на несколько запросов, чтобы вам не нужно было сортировать и отправлять декартово произведение Actvty и Pmnt для каждого Rqst . Если у a Rqst есть 50 Actvty секунд и 4 Pmnt секунды, запрос вернет для этого 200 строк Rqst .

Кроме того, он присоединяется Pmnt несколько раз без видимой причины, что не помогает.

Комментарии:

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

2. Нет, по-моему, это похоже на жучок.