Как получить план выполнения запроса? - PullRequest
324 голосов
/ 09 сентября 2011

В Microsoft SQL Server как я могу получить план выполнения запроса для хранимой процедуры?

Ответы [ 10 ]

484 голосов
/ 09 сентября 2011

Существует несколько способов получения плана выполнения, который будет зависеть от ваших обстоятельств.Обычно вы можете использовать SQL Server Management Studio для получения плана, однако, если по какой-то причине вы не можете выполнить свой запрос в SQL Server Management Studio, вам может быть полезно иметь возможность получить план с помощью SQL Server Profiler или путем проверкикэш плана.

Метод 1 - Использование SQL Server Management Studio

SQL Server поставляется с парой полезных функций, которые очень упрощают захват плана выполнения, просто убедитесь, что "Пункт меню «Включить фактический план выполнения» (находится в меню «Запрос») установлен и запускает ваш запрос как обычно.

Include Action Execution Plan menu item

Если вы пытаетесь получить план выполнения дляоператоры в хранимой процедуре, то вы должны выполнить хранимую процедуру, например так:

exec p_Example 42

Когда ваш запрос завершится, вы увидите дополнительную вкладку под названием «План выполнения», появившуюся на панели результатов.Если вы выполнили много операторов, вы можете увидеть много планов, отображаемых на этой вкладке.

Screenshot of an Execution Plan

Отсюда вы можете просмотреть план выполнения в SQL Server Management Studio или щелкнуть правой кнопкой мыши назапланируйте и выберите «Сохранить план выполнения как ...», чтобы сохранить план в файл в формате XML.

Метод 2 - Использование параметров SHOWPLAN

Этот метод очень похож на метод 1 (на самом деле это то, что делает SQL Server Management Studio внутренне), однако я включил его для полноты или если у вас нет SQL Server Management Studio.

Перед тем как выполнить запрос, запустите one из следующих утверждений.Этот оператор должен быть единственным оператором в пакете, т. Е. Вы не можете одновременно выполнить другой оператор:

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

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

Как только выКогда вы закончите, вы можете отключить эту опцию с помощью следующего оператора:

SET <<option>> OFF

Сравнение форматов плана выполнения

Если у вас нет сильных предпочтений, я рекомендую использовать опцию STATISTICS XML.Этот параметр эквивалентен параметру «Включить фактический план выполнения» в SQL Server Management Studio и предоставляет наибольшую информацию в наиболее удобном формате.

  • SHOWPLAN_TEXT - отображает базовый текстовый примерный план выполнения, без выполнения запроса
  • SHOWPLAN_ALL - отображает текстовый оценочный план выполнения с оценками затрат, без выполнения запроса
  • SHOWPLAN_XML - отображает основанный на XML расчетный план выполнения с оценками затратбез выполнения запроса.Это эквивалентно параметру «Показать примерный план выполнения ...» в SQL Server Management Studio.
  • STATISTICS PROFILE - выполняет запрос и отображает текстовый план фактического выполнения.
  • STATISTICS XML - выполняет запрос и отображает фактический план выполнения на основе XML.Это эквивалентно параметру «Включить фактический план выполнения» в SQL Server Management Studio.

Метод 3 - Использование SQL Server Profiler

Если вы не можете выполнить запрос напрямую (или ваш запрос не выполняется медленно, когда вы выполняете его напрямую (помните, что мы хотим, чтобы план запроса выполнялся плохо), тогда вы можете захватить план, используя трассировку SQL Server Profiler.Идея состоит в том, чтобы выполнить ваш запрос во время трассировки, которая захватывает одно из событий «Showplan».

Обратите внимание, что в зависимости от нагрузки вы можете использовать этот метод в производственной среде, однако вам, очевидно, следует соблюдать осторожность. Механизмы профилирования SQL Server разработаны таким образом, чтобы минимизировать влияние на базу данных, но это не означает, что никакого влияния на производительность не будет . У вас также могут возникнуть проблемы с фильтрацией и определением правильного плана в вашей трассировке, если ваша база данных интенсивно используется. Вам, очевидно, следует обратиться к администратору базы данных, чтобы узнать, довольны ли они тем, что вы делаете это на своей драгоценной базе данных! Откройте SQL Server Profiler и создайте новую трассировку, соединяющуюся с нужной базой данных, для которой вы хотите записать трассировку. На вкладке «Выбор событий» установите флажок «Показать все события», проверьте строку «Производительность» -> «Showplan XML» и запустите трассировку. Пока трассировка выполняется, делайте все, что вам нужно, чтобы запустить медленный запрос. Дождитесь завершения запроса и остановите трассировку. Чтобы сохранить трассировку, щелкните правой кнопкой мыши план xml в SQL Server Profiler и выберите «Извлечь данные события ...», чтобы сохранить план в файл в формате XML. План, который вы получаете, эквивалентен параметру «Включить фактический план выполнения» в SQL Server Management Studio.

Метод 4 - Проверка кэша запросов

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

Мы проверяем кэш плана, запрашивая у SQL Server DMV . Ниже приведен базовый запрос, в котором будут перечислены все кэшированные планы запросов (в формате xml) вместе с текстом SQL. В большинстве баз данных вам также нужно будет добавить дополнительные условия фильтрации, чтобы отфильтровать результаты по интересующим вас планам.

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

Выполните этот запрос и нажмите на XML плана, чтобы открыть план в новом окне - щелкните правой кнопкой мыши и выберите «Сохранить план выполнения как ...», чтобы сохранить план в файл в формате XML.

Примечания:

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

Невозможно записать план выполнения для зашифрованных хранимых процедур.

"фактические" и "расчетные" планы выполнения

фактический план выполнения - это тот, в котором SQL Server фактически выполняет запрос, тогда как предполагаемый план выполнения SQL Server определяет, что он будет делать без выполнения запрос. Несмотря на логическую эквивалентность, фактический план выполнения гораздо полезнее, поскольку он содержит дополнительные сведения и статистику о том, что на самом деле произошло при выполнении запроса. Это важно при диагностике проблем, при которых оценки SQL Server отключены (например, когда статистика устарела).

Как мне интерпретировать план выполнения запроса?

Это тема, достойная (бесплатной) книги сама по себе.

Смотри также:

40 голосов
/ 09 сентября 2011

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

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

Пример StartCapture Определение

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL 

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

Пример StopCapture Определение

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql), 
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName  

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO
17 голосов
/ 09 сентября 2016

Если вы используете Microsoft SQL Server Management Studio

  • Для Предполагаемый план запроса Вы можете нажать Ctrl + L или следующую кнопку.

enter image description here

  • Для Фактический план запроса , вы можете нажать Ctrl+ M или следующая кнопка перед выполнением запроса.

enter image description here

  • Для Live Query Plan , (только в SSMS 2016) используйте следующую кнопку перед выполнением запроса.

enter image description here

15 голосов
/ 17 июля 2017

Помимо методов, описанных в предыдущих ответах, вы также можете использовать бесплатное средство просмотра плана выполнения и инструмент оптимизации запросов ApexSQL Plan (в который я недавно врезался).

Вы можете установить и интегрировать ApexSQL Plan в SQL Server Management Studio, чтобы планы выполнения можно было просматривать непосредственно из SSMS.

Просмотр планов выполнения в ApexSQL Plan

  1. Нажмите кнопку Новый запрос в SSMS и вставьте текст запроса в текстовое окно запроса. Щелкните правой кнопкой мыши и выберите «Показать примерный план выполнения» из контекстного меню.

New Query button in SSMS

  1. Диаграммы плана выполнения будут показаны на вкладке План выполнения в разделе результатов. Затем щелкните правой кнопкой мыши план выполнения и в контекстном меню выберите параметр «Открыть в ApexSQL Plan».

Execution Plan

  1. Предполагаемый план выполнения будет открыт в ApexSQL Plan и может быть проанализирован для оптимизации запросов.

Estimated execution plan

Просмотр фактических планов выполнения в ApexSQL Plan

Чтобы просмотреть Фактический план выполнения запроса, продолжите со 2-го шага, упомянутого ранее, но теперь, когда отображается Предполагаемый план, нажмите кнопку «Факт» на главной панели ленты в плане ApexSQL.

click the “Actual” button from the main ribbon bar

После нажатия кнопки «Фактически» будет показан Фактический план выполнения с подробным предварительным просмотром параметров стоимости вместе с другими данными плана выполнения.

Actual execution plan

Дополнительную информацию о просмотре планов выполнения можно найти по этой ссылке .

13 голосов
/ 09 июня 2014

Мой любимый инструмент для получения и глубокого анализа планов выполнения запросов - SQL Sentry Plan Explorer .Это гораздо более удобный для пользователя, удобный и всеобъемлющий для детального анализа и визуализации планов выполнения, чем SSMS.

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

SQL Sentry Plan Explorer window screen shot

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

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

ОБНОВЛЕНИЕ: (Благодаря Martin Smith ) Plan Explorer теперь бесплатен!Подробнее см. http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view.

7 голосов
/ 11 ноября 2015

Планы запросов можно получить из сеанса расширенных событий через событие query_post_execution_showplan. Вот пример сеанса XEvent:

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))) 
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

После создания сеанса (в SSMS) перейдите в Обозреватель объектов и углубитесь в Управление | Расширенные события | Сессии. Щелкните правой кнопкой мыши сеанс «GetExecutionPlan» и запустите его. Щелкните правой кнопкой мыши еще раз и выберите «Просмотр данных в реальном времени».

Затем откройте новое окно запроса и выполните один или несколько запросов. Вот один для AdventureWorks:

USE AdventureWorks;
GO

SELECT p.Name AS ProductName, 
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p 
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID 
ORDER BY ProductName DESC;
GO

Через несколько секунд вы должны увидеть некоторые результаты на вкладке «GetExecutionPlan: Live Data». Щелкните одно из событий query_post_execution_showplan в сетке, а затем перейдите на вкладку «План запроса» под сеткой. Это должно выглядеть примерно так:

enter image description here

РЕДАКТИРОВАТЬ : код XEvent и снимок экрана были созданы из SQL / SSMS 2012 с пакетом обновления 2 (SP2). Если вы используете SQL 2008 / R2, вы можете настроить скрипт, чтобы он запустился. Но эта версия не имеет графического интерфейса, поэтому вам придется извлечь XML showplan, сохранить его как файл * .sqlplan и открыть его в SSMS. Это громоздко. XEvents не существовало в SQL 2005 или более ранних версиях. Поэтому, если вы не используете SQL 2012 или более позднюю версию, я настоятельно рекомендую опубликовать здесь один из других ответов.

5 голосов
/ 25 мая 2018

Начиная с SQL Server 2016+, была добавлена ​​функция хранилища запросов для мониторинга производительности. Это дает представление о выборе плана запроса и производительности. Это не полная замена трассировки или расширенных событий, но по мере развития от версии к версии мы можем получить полнофункциональное хранилище запросов в будущих выпусках SQL Server. Основной поток Query Store

  1. Существующие компоненты SQL Server взаимодействуют с хранилищем запросов с помощью диспетчера хранилища запросов.
  2. Диспетчер хранилища запросов определяет, какое хранилище следует использовать, а затем передает выполнение этому хранилищу (статистика планирования или выполнения или статистика ожидания запроса)
    • Plan Store - Сохранение информации о плане выполнения
    • Runtime Stats Store - Сохранение информации статистики выполнения
    • Query Wait Stats Store - Сохраняющаяся информация статистики ожидания.
  3. Планирование, статистика времени выполнения и хранилище ожидания используют хранилище запросов в качестве расширения SQL Server.

enter image description here

  1. Включение хранилища запросов : хранилище запросов работает на уровне базы данных на сервере.

    • По умолчанию хранилище запросов неактивно для новых баз данных.
    • Нельзя включить хранилище запросов для главной или tempdb базы данных.
    • Доступен DMV

      sys.database_query_store_options (Transact-SQL)

  2. Сбор информации в хранилище запросов : Мы собираем всю доступную информацию из трех хранилищ, используя Query Store DMV (представления управления данными).

    • Магазин плана запросов: Сохранение информации плана выполнения, и она отвечает за сбор всей информации, связанной с компиляцией запроса.

      sys.query_store_query (Transact-SQL) sys.query_store_plan (Transact-SQL) sys.query_store_query_text (Transact-SQL)

    • Runtime Stats Store: Сохранение информации статистики выполнения, и это, вероятно, наиболее часто обновляемое хранилище. Эта статистика представляет данные выполнения запроса.

      sys.query_store_runtime_stats (Transact-SQL)

    • Статистика запросов Query Wait Store: Сохранение и сбор статистических данных ожидания.

      sys.query_store_wait_stats (Transact-SQL)

ПРИМЕЧАНИЕ: Хранилище статистики ожидания запросов доступно только в SQL Server 2017 +

3 голосов
/ 25 августа 2018

Как и в SQL Server Management Studio (уже объяснено), это также возможно с Datagrip, как объяснено здесь .

  1. Щелкните правой кнопкой мыши оператор SQL и выберите Объяснить план.
  2. На панели «Вывод» нажмите «План».
  3. По умолчанию вы видите древовидное представление запроса. Чтобы увидеть план запроса, щелкните значок Показать визуализацию или нажмите Ctrl + Shift + Alt + U
3 голосов
/ 05 июня 2018

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

Планы запросов часто слишком сложны, чтобы быть представленными встроенным типом столбца XML, который имеет ограничение в 127 уровней вложенных элементов.Это одна из причин, по которой sys.dm_exec_query_plan может возвращать NULL или даже выдавать ошибку в более ранних версиях MS SQL, поэтому обычно безопаснее использовать sys.dm_exec_text_query_plan .Последний также имеет полезную бонусную функцию выбора плана для конкретного оператора , а не для всей партии.Вот как вы можете использовать его для просмотра планов текущих операторов:

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

Однако текстовый столбец в результирующей таблице не очень удобен по сравнению со столбцом XML.Чтобы иметь возможность щелкнуть по результату, который будет открыт на отдельной вкладке в виде диаграммы, без необходимости сохранять его содержимое в файле, вы можете использовать небольшой прием (помните, что вы не можете просто использовать CAST(... AS XML)), хотя это будет толькоработа для одного ряда:

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT
0 голосов
/ 14 июля 2019

Объяснение плана выполнения может быть очень подробным и занимать довольно много времени на чтение, но в итоге, если вы используете 'объяснение' перед запросом, оно должно дать вам много информации, включая то, какие части были выполнены первыми и так далее.Если вы хотите прочитать немного больше информации об этом, я собрал небольшой блог об этом, который также указывает на правильных ссылок.https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

...