Устранение неполадок с медленным запросом в выделенном пуле SQL

Область применения: Azure Synapse Analytics

Эта статья поможет вам определить причины и применить способы устранения распространенных проблем с производительностью запросов в выделенном пуле SQL Azure Synapse Analytics.

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

Примечание.

Перед попыткой открыть эту записную книжку убедитесь, что на локальном компьютере установлена среда Azure Data Studio. Чтобы установить его, перейдите в раздел Узнайте, как установить Azure Data Studio.

Важно!

Большинство из сообщаемых проблем с производительностью вызваны следующими причинами:

  • Устаревшая статистика
  • Неработоспособные кластеризованные индексы columnstore (CCIs)

Чтобы сэкономить время на устранение неполадок, убедитесь, что статистика создана, а также обновлены актуальные ИИС.

Шаг 1. Определение request_id (или QID)

Медленный request_id запрос необходим для исследования потенциальных причин медленного запроса. Используйте следующий скрипт в качестве отправной точки для определения запроса, который требуется устранить. После определения медленного запроса запишите request_id значение.

-- Monitor active queries
SELECT *
FROM sys.dm_pdw_exec_requests
WHERE [status] NOT IN ('Completed','Failed','Cancelled')
AND session_id <> session_id()
-- AND [label] = '<YourLabel>'
-- AND resource_allocation_percentage is not NULL
ORDER BY submit_time DESC;

-- Find top 10 longest running queries
SELECT TOP 10 *
FROM sys.dm_pdw_exec_requests
ORDER BY total_elapsed_time DESC;

Чтобы лучше ориентироваться на медленные запросы, используйте следующие советы при выполнении скрипта:

  • Сортируйте по или submit_time DESCtotal_elapsed_time DESC для того, чтобы в верхней части результирующих наборов присутствовали самые длительные запросы.

  • Используйте OPTION(LABEL='<YourLabel>') в запросах, а затем отфильтруйте label столбец для их идентификации.

  • Если вы знаете, что целевая инструкция содержится в пакете, рекомендуется отфильтровать все идентификаторы QID, для которых нет значения resource_allocation_percentage .

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

Шаг 2. Определение времени запроса

Выполните следующий скрипт, чтобы найти шаг, который может привести к проблеме с производительностью запроса. Обновите переменные в скрипте значениями, описанными в следующей таблице. Измените @ShowActiveOnly значение на 0, чтобы получить полную картину распределенного плана. Запишите StepIndexзначения , Phaseи Description медленного шага, определяемого в результирующем наборе.

Параметр Описание
@QID Значение, полученное request_id на шаге 1
@ShowActiveOnly 0 . Отображение всех шагов для запроса
1. Отображение только активного шага
DECLARE @QID VARCHAR(16) = '<request_id>', @ShowActiveOnly BIT = 1; 
-- Retrieve session_id of QID
DECLARE @session_id VARCHAR(16) = (SELECT session_id FROM sys.dm_pdw_exec_requests WHERE request_id = @QID);
-- Blocked by Compilation or Resource Allocation (Concurrency)
SELECT @session_id AS session_id, @QID AS request_id, -1 AS [StepIndex], 'Compilation' AS [Phase],
   'Blocked waiting on '
       + MAX(CASE WHEN waiting.type = 'CompilationConcurrencyResourceType' THEN 'Compilation Concurrency'
                  WHEN waiting.type LIKE 'Shared-%' THEN ''
                  ELSE 'Resource Allocation (Concurrency)' END)
       + MAX(CASE WHEN waiting.type LIKE 'Shared-%' THEN ' for ' + REPLACE(waiting.type, 'Shared-', '')
             ELSE '' END) AS [Description],
   MAX(waiting.request_time) AS [StartTime], GETDATE() AS [EndTime],
   DATEDIFF(ms, MAX(waiting.request_time), GETDATE())/1000.0 AS [Duration],
   NULL AS [Status], NULL AS [EstimatedRowCount], NULL AS [ActualRowCount], NULL AS [TSQL]
FROM sys.dm_pdw_waits waiting
WHERE waiting.session_id = @session_id
   AND ([type] LIKE 'Shared-%' OR
      [type] in ('ConcurrencyResourceType', 'UserConcurrencyResourceType', 'CompilationConcurrencyResourceType'))
   AND [state] = 'Queued'
GROUP BY session_id 
-- Blocked by another query
UNION ALL
SELECT @session_id AS session_id, @QID AS request_id, -1 AS [StepIndex], 'Compilation' AS [Phase],
   'Blocked by ' + blocking.session_id + ':' + blocking.request_id + ' when requesting ' + waiting.type + ' on '
   + QUOTENAME(waiting.object_type) + waiting.object_name AS [Description],
   waiting.request_time AS [StartTime], GETDATE() AS [EndTime],
   DATEDIFF(ms, waiting.request_time, GETDATE())/1000.0 AS [Duration],
   NULL AS [Status], NULL AS [EstimatedRowCount], NULL AS [ActualRowCount],
   COALESCE(blocking_exec_request.command, blocking_exec_request.command2) AS [TSQL]
FROM sys.dm_pdw_waits waiting
   INNER JOIN sys.dm_pdw_waits blocking
      ON waiting.object_type = blocking.object_type
      AND waiting.object_name = blocking.object_name
   INNER JOIN sys.dm_pdw_exec_requests blocking_exec_request
      ON blocking.request_id = blocking_exec_request.request_id
WHERE waiting.session_id = @session_id AND waiting.state = 'Queued'
   AND blocking.state = 'Granted' AND waiting.type != 'Shared' 
-- Request Steps
UNION ALL
SELECT @session_id AS session_id, @QID AS request_id, step_index AS [StepIndex],
       'Execution' AS [Phase], operation_type + ' (' + location_type + ')' AS [Description],
       start_time AS [StartTime], end_time AS [EndTime],
       total_elapsed_time/1000.0 AS [Duration], [status] AS [Status],
       CASE WHEN estimated_rows > -1 THEN estimated_rows END AS [EstimatedRowCount],
       CASE WHEN row_count > -1 THEN row_count END AS [ActualRowCount],
       command AS [TSQL]
FROM sys.dm_pdw_request_steps
WHERE request_id = @QID
   AND [status] = CASE @ShowActiveOnly WHEN 1 THEN 'Running' ELSE [status] END
ORDER BY StepIndex;

Шаг 3. Просмотр сведений о шаге

Выполните следующий скрипт, чтобы просмотреть сведения о шаге, указанном на предыдущем шаге. Обновите переменные в скрипте значениями, описанными в следующей таблице. Измените @ShowActiveOnly значение на 0, чтобы сравнить все сроки распределения. Запишите wait_type значение для дистрибутива, которое может вызвать проблему с производительностью.

Параметр Описание
@QID Значение, полученное request_id на шаге 1
@StepIndex Значение StepIndex , определенное на шаге 2.
@ShowActiveOnly 0 — отображение всех распределений для заданного StepIndex значения
1. Отображение только текущих активных распределений для заданного StepIndex значения
DECLARE @QID VARCHAR(16) = '<request_id>', @StepIndex INT = <StepIndex>, @ShowActiveOnly BIT = 1;
WITH dists
AS (SELECT request_id, step_index, 'sys.dm_pdw_sql_requests' AS source_dmv,
       distribution_id, pdw_node_id, spid, 'NativeSQL' AS [type], [status],
       start_time, end_time, total_elapsed_time, row_count
    FROM sys.dm_pdw_sql_requests
    WHERE request_id = @QID AND step_index = @StepIndex
    UNION ALL
    SELECT request_id, step_index, 'sys.dm_pdw_dms_workers' AS source_dmv,
       distribution_id, pdw_node_id, sql_spid AS spid, [type],
       [status], start_time, end_time, total_elapsed_time, rows_processed as row_count
    FROM sys.dm_pdw_dms_workers
    WHERE request_id = @QID AND step_index = @StepIndex
   )
SELECT sr.step_index, sr.distribution_id, sr.pdw_node_id, sr.spid,
       sr.type, sr.status, sr.start_time, sr.end_time,
       sr.total_elapsed_time, sr.row_count, owt.wait_type, owt.wait_time
FROM dists sr
   LEFT JOIN sys.dm_pdw_nodes_exec_requests owt
      ON sr.pdw_node_id = owt.pdw_node_id
         AND sr.spid = owt.session_id
         AND ((sr.source_dmv = 'sys.dm_pdw_sql_requests'
                 AND sr.status = 'Running') -- sys.dm_pdw_sql_requests status
              OR (sr.source_dmv = 'sys.dm_pdw_dms_requests'
                     AND sr.status not LIKE 'Step[CE]%')) -- sys.dm_pdw_dms_workers final statuses
WHERE sr.request_id = @QID
      AND ((sr.source_dmv = 'sys.dm_pdw_sql_requests' AND sr.status =
               CASE WHEN @ShowActiveOnly = 1 THEN 'Running' ELSE sr.status END)
           OR (sr.source_dmv = 'sys.dm_pdw_dms_workers' AND sr.status NOT LIKE
                  CASE WHEN @ShowActiveOnly = 1 THEN 'Step[CE]%' ELSE '' END))
      AND sr.step_index = @StepIndex
ORDER BY distribution_id

Шаг 4. Диагностика и устранение рисков

Проблемы этапа компиляции

Заблокировано: параллелизм компиляции

Блоки компиляции параллелизма встречаются редко. Однако если вы столкнулись с блоком такого типа, это означает, что большой объем запросов был отправлен в течение короткого времени и был поставлен в очередь для начала компиляции.

Устранение рисков

Уменьшите количество запросов, отправляемых одновременно.


Заблокировано: выделение ресурсов

Блокировка для выделения ресурсов означает, что запрос ожидает выполнения на основе:

  • Объем памяти, предоставленный на основе назначения класса ресурсов или группы рабочей нагрузки, связанного с пользователем.
  • Объем доступной памяти в системе или группе рабочей нагрузки.
  • (Необязательно) Важность группы или классификатора рабочей нагрузки.

Устранение рисков

Сложный запрос или более старый синтаксис JOIN

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

  • Включает большое количество соединений и (или) вложенных запросов (сложный запрос).
  • Использует соединения в предложении FROM (не соединения в стиле ANSI-92).

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

Устранение рисков

  • Используйте соединения в стиле ANSI-92.
  • Добавление указаний запроса: OPTION(FORCE ORDER, USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION')). Дополнительные сведения см. в разделе FORCE ORDER и кратность оценки (SQL Server).
  • Разбейте запрос на несколько менее сложных шагов.
Длительное выполнение DROP TABLE или TRUNCATE TABLE

Для экономии времени выполнения инструкции DROP TABLE и TRUNCATE TABLE будут откладывать очистку хранилища на фоновый процесс. Однако если рабочая нагрузка выполняет большое количество инструкций DROP/TRUNCATE TABLE за короткий промежуток времени, возможно, метаданные становятся переполненными и последующие DROP/TRUNCATE TABLE инструкции выполняются медленно.

Устранение рисков

Определите период обслуживания, остановите все рабочие нагрузки и запустите DBCC SHRINKDATABASE для принудительной немедленной очистки ранее удаленных или усеченных таблиц.


Неработоспособные ccis (как правило)

Плохая работоспособность кластеризованного индекса columnstore (CCI) требует дополнительных метаданных, что может привести к тому, что оптимизатор запросов займет больше времени для определения оптимального плана. Чтобы избежать этой ситуации, убедитесь, что все ваши CCIs находятся в хорошем состоянии.

Устранение рисков

Оценка и исправление работоспособности кластеризованного индекса columnstore в выделенном пуле SQL.


Задержка автоматического создания статистики

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

Устранение рисков

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


Автоматическое создание времени ожидания статистики

Параметр автоматического создания статистики по умолчанию помогает убедитьсяON, AUTO_CREATE_STATISTICS что оптимизатор запросов может принимать правильные решения о распределенных планах. Автоматическое создание статистики происходит в ответ на инструкцию SELECT и имеет 5-минутное пороговое значение для завершения. Если размер данных и (или) количество создаваемых статистических данных требует больше, чем 5-минутное пороговое значение, автоматическое создание статистики будет прекращено, чтобы запрос можно было продолжить выполнение. Сбой при создании статистики может негативно повлиять на способность оптимизатора запросов создавать эффективный распределенный план выполнения, что приводит к низкой производительности запросов.

Устранение рисков

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

Проблемы с этапом выполнения

  • Используйте следующую таблицу для анализа результирующий набор на шаге 2. Определите сценарий и проверка распространенные причины получения подробных сведений и возможных шагов по устранению рисков.

    Сценарий Общая причина
    EstimatedRowCount/ActualRowCount< 25% Неточные оценки
    Значение Description указывает, BroadcastMoveOperation а запрос ссылается на реплицированную таблицу. Некэшированные реплицированные таблицы
    1. @ShowActiveOnly = 0
    2. Наблюдается большое или непредвиденное количество шагов (step_index).
    3. Типы данных столбцов соединения не идентичны между таблицами.
    Несовпадение типа или размера данных
    1. Значение Description указывает HadoopBroadcastOperation, HadoopRoundRobinOperation или HadoopShuffleOperation.
    2. Значение total_elapsed_time заданного step_index является несогласованным между выполнениями.
    Нерегламентированные запросы к внешней таблице
  • Проверьте значение, полученное total_elapsed_time на шаге 3. Если он значительно выше в нескольких распределениях на заданном шаге, выполните следующие действия:

    1. Проверьте распределение данных для каждой таблицы, на которую ссылается TSQL поле, для связанной step_id , выполнив следующую команду для каждой из них:

      DBCC PDW_SHOWSPACEUSED(<table>);
      
    2. Если <минимальное значение> строк или< максимальное значение>> строк 0,1, перейдите к разделу Неравномерное распределение данных (сохранение).

    3. В противном случае перейдите в раздел Перекос данных в режиме выполнения.

Неточные оценки

Доведите статистику до актуальности, чтобы убедиться, что оптимизатор запросов создает оптимальный план. Если предполагаемое число строк значительно меньше фактического числа, необходимо сохранить статистику.

Устранение рисков

Создание и обновление статистики.


Некэшированные реплицированные таблицы

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

Устранение рисков

Несовпадение типа или размера данных

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

Устранение рисков

Перестройте таблицы, чтобы исправить связанные столбцы таблицы, которые не имеют одинаковых типов данных и размера.


Нерегламентированные запросы к внешней таблице

Запросы к внешним таблицам разработаны с целью массовой загрузки данных в выделенный пул SQL. Нерегламентированные запросы к внешним таблицам могут страдать от переменной длительности из-за внешних факторов, таких как одновременные действия контейнера хранилища.

Устранение рисков

Сначала загрузите данные в выделенный пул SQL , а затем запросите загруженные данные.


Неравномерное распределение данных (сохранено)

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

Устранение рисков

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


Перекос данных в режиме выполнения

Перекос данных в режиме выполнения является вариантом проблемы с неравномерностью (сохранением) данных . Но распределение данных на диске не является перекосом. Характер распределенного плана для определенных фильтров или сгруппированных данных вызывает ShuffleMoveOperation операцию типа. Эта операция создает отклоненные выходные данные, которые будут использоваться ниже.

Устранение рисков

  • Убедитесь, что статистика создана и обновлена.
  • Измените порядок столбцов GROUP BY , чтобы привести к столбцу с более высоким кратностью.
  • Создание статистики по нескольким столбцам, если соединения охватывают несколько столбцов.
  • Добавьте указание OPTION(FORCE_ORDER) запроса в запрос.
  • Рефакторинг запроса.

Проблемы с типом ожидания

Если ни одна из описанных выше распространенных проблем не относится к запросу, данные на шаге 3 предоставляют возможность определить, какие типы ожидания (в wait_type и wait_time) мешают обработке запросов на самом длительном шаге. Существует большое количество типов ожидания, и они группируются по связанным категориям из-за аналогичных мер по устранению рисков. Чтобы найти категорию ожидания на шаге запроса, выполните следующие действия:

  1. На шаге 3 определите, wait_type что занимает больше всего времени.
  2. Найдите тип ожидания в таблице сопоставления категорий ожидания и определите категорию ожидания, включаемую в.
  3. Разверните раздел, связанный с категорией ожидания, из следующего списка для рекомендуемых мер по устранению рисков.
Компиляции

Выполните следующие действия, чтобы устранить проблемы с типом ожидания в категории Компиляция.

  1. Перестройте индексы для всех объектов, участвующих в проблемном запросе.
  2. Обновление статистики по всем объектам, участвующим в проблемном запросе.
  3. Снова протестируйте проблемный запрос, чтобы проверить, сохраняется ли проблема.

Если проблема не исчезнет, выполните следующие действия:

  1. Создайте файл .sql с помощью:

    SET QUERY_DIAGNOSTICS ON; <Your_SQL>; SET QUERY_DIAGNOSTICS OFF;
    
  2. Откройте окно командной строки и выполните следующую команду:

    sqlcmd −S <servername>.database.windows.net −d <databasename> −U <username> −G −I −i .\<sql_file_name>.sql −y0 −o .\<output_file_name>.txt
    
  3. Откройте <.txt output_file_name> в текстовом редакторе. Найдите и скопируйте вставьте планы выполнения на уровне распространения (строки, начинающиеся с <ShowPlanXML>) из самого длинного шага, определенного на шаге 2 , в отдельные текстовые файлы с расширением .sqlplan .

    Примечание: На каждом шаге распределенного плана обычно записывается 60 планов выполнения на уровне распределения. Убедитесь, что вы готовите и сравниваете планы выполнения на одном шаге распределенного плана.

  4. Запрос на шаг 3 часто показывает несколько распределений, которые занимают гораздо больше времени, чем другие. В SQL Server Management Studio сравните планы выполнения на уровне распределения (из созданных sqlplan-файлов) длительного дистрибутива с быстрым распределением, чтобы проанализировать потенциальные причины различий.

Блокировка, рабочий поток
  • Рассмотрите возможность изменения таблиц, которые претерпевают частые небольшие изменения, чтобы использовать индекс хранилища строк вместо CCI.
  • Пакетируйте изменения и обновляйте целевой объект с большим количеством строк на менее частой основе.
Операции ввода-вывода буфера, другие операции ввода-вывода на диске, операции ввода-вывода журнала Tran

Неработоспособные ccis

Неработоспособные ccIs способствуют увеличению объема операций ввода-вывода, ЦП и памяти, что, в свою очередь, негативно влияет на производительность запросов. Чтобы устранить эту проблему, попробуйте один из следующих методов:

Устаревшая статистика

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

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

Тяжелые рабочие нагрузки операций ввода-вывода

Общая рабочая нагрузка может считывать большие объемы данных. Выделенные пулы SQL Synapse масштабировать ресурсы в соответствии с DWU. Чтобы повысить производительность, рассмотрите один из следующих вариантов:

ЦП, параллелизм
Сценарий Устранение рисков
Плохое здоровье CCI Оценка и исправление работоспособности кластеризованного индекса columnstore в выделенном пуле SQL
Пользовательские запросы содержат преобразования Перемещение всей логики форматирования и другой логики преобразования в процессы ETL, чтобы хранить отформатированные версии
Неправильное распределение приоритетов рабочей нагрузки Реализация изоляции рабочей нагрузки
Недостаточно DWU для рабочей нагрузки Рассмотрите возможность увеличения вычислительных ресурсов

Сетевые операции ввода-вывода

Если проблема возникает во время RETURN операции на шаге 2,

  • Уменьшите количество параллельных процессов.
  • Масштабируйте наиболее затронутый процесс на другом клиенте.

Для всех других операций перемещения данных, скорее всего, проблемы с сетью, как представляется, будут внутренними для выделенного пула SQL. Чтобы быстро устранить эту проблему, выполните следующие действия.

  1. Масштабирование выделенного пула SQL до DW100c
  2. Уменьшение масштаба до нужного уровня DWU
SQL CLR

Избегайте частого использования функции, FORMAT() реализуя альтернативный способ преобразования данных (например, CONVERT() со стилем).