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

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

Ответ 1

Существует несколько способов получения плана выполнения, который использовать будет зависеть от ваших обстоятельств. Обычно вы можете использовать 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.

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

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

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

Обратите внимание, что в зависимости от нагрузки вы можете использовать этот метод в рабочей среде, однако вы должны, очевидно, соблюдать осторожность. Механизмы профилирования SQL Server предназначены для минимизации влияния на базу данных, но это не означает, что влияние производительности не будет. У вас может также возникнуть проблема с фильтрацией и определением правильного плана в вашей трассе, если ваша база данных находится под большим использованием. Вы, очевидно, должны проверить свой администратор базы данных, чтобы убедиться, что они довольны тем, что вы делаете это в своей драгоценной базе данных!

  • Откройте SQL Server Profiler и создайте новую трассировку, соединяющую нужную базу данных, с которой вы хотите записать трассировку.
  • На вкладке "Выбор событий" установите флажок "Показать все события", проверьте строку "Производительность" → "Showplan XML" и запустите трассировку.
  • Пока трассировка работает, сделайте все, что вам нужно, чтобы запустить медленный запрос.
  • Дождитесь завершения запроса и остановки трассировки.
  • Чтобы сохранить трассировку, щелкните правой кнопкой мыши по плану xml в профиле SQL Server и выберите "Извлечь данные о событиях...", чтобы сохранить план в файл в формате XML.

Полученный вами план эквивалентен опции "Включить фактический план выполнения" в SQL Server Management Studio.

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

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

Мы проверяем кеш плана, запрашивая SQL Server DMVs. Ниже приведен базовый запрос, в котором будут перечислены все кэшированные планы запросов (как 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-серверов отключены (например, когда статистика устарела).

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

Это тема, достойная достаточно для бесплатного book.

См. также:

Ответ 2

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

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

Ответ 3

Предполагая, что вы используете Microsoft SQL Server Management Studio

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

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

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

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

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

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

Ответ 4

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

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

Просмотр прогнозируемых планов выполнения в Плане ApexSQL

  • Нажмите кнопку Новый запрос в SSMS и вставьте текст запроса в текстовое окно запроса. Щелкните правой кнопкой мыши и выберите "Отображать примерный план выполнения" в контекстном меню.

Новая кнопка запроса в SSMS

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

План выполнения

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

Предполагаемый план выполнения

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

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

нажмите кнопку

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

Фактический план выполнения

Более подробную информацию о просмотре планов выполнения можно найти, следуя этой ссылке.

Ответ 5

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

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

Исходный экран окна Sentry Plan Explorer

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

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

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

Ответ 6

Планы запросов могут быть получены из сеанса расширенных событий через событие 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) перейдите в обозреватель объектов и углубитесь в Management | Расширенные события | Сессии. Щелкните правой кнопкой мыши сеанс "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 w/SP2. Если вы используете SQL 2008/R2, вы можете настроить скрипт для его запуска. Но эта версия не имеет графического интерфейса, поэтому вам придется извлечь XML showplan, сохранить его как файл *.sqlplan и открыть его в SSMS. Это громоздко. XEvents не существовало в SQL 2005 или более ранних версиях. Поэтому, если вы не используете SQL 2012 или более позднюю версию, я настоятельно рекомендую один из других ответов, опубликованных здесь.

Ответ 7

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

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

enter image description here

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

    • По умолчанию хранилище запросов неактивно для новых баз данных.
    • Вы не можете включить хранилище запросов для базы данных master или 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)

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

      sys.query_store_runtime_stats (Transact-SQL)

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

      sys.query_store_wait_stats (Transact-SQL)

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

Ответ 8

Здесь важно знать одну вещь в дополнение ко всему сказанному ранее.

Планы запросов часто слишком сложны, чтобы быть представленными встроенным типом столбца 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

Ответ 9

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

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

Ответ 10

Вы также можете сделать это через powershell, используя SET STATISTICS XML ON, чтобы получить реальный план. Я написал это так, что он объединяет планы с несколькими утверждениями в один план;

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName'_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()

Ответ 11

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

Ответ 12

  Как я объяснял в этой статье, есть два типа плана выполнения, которые вы можете получить при использовании SQL Server.

Предполагаемый план выполнения

Предполагаемый план выполнения создается оптимизатором без выполнения запроса SQL.

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

SET SHOWPLAN_ALL ON

Теперь при выполнении следующего SQL-запроса:

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

SQL Server создаст следующий примерный план выполнения:

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

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

SET SHOWPLAN_ALL OFF

Примерный план SQL Server Management Studio

В приложении SQL Server Management Studio вы можете легко получить приблизительный план выполнения для любого запроса SQL, нажав сочетание клавиш CTRL+L.

enter image description here

Фактический план выполнения

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

Чтобы получить фактический план выполнения на SQL Server, вам нужно включить настройки STATISTICS IO, TIME, PROFILE, как показано следующей командой SQL:

SET STATISTICS IO, TIME, PROFILE ON

Теперь при выполнении предыдущего запроса SQL Server будет генерировать следующий план выполнения:

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

После выполнения запроса мы заинтересованы в том, чтобы получить фактический план выполнения, вам необходимо отключить настройки STATISTICS IO, TIME, PROFILE ON следующим образом:

SET STATISTICS IO, TIME, PROFILE OFF

Фактический план SQL Server Management Studio

В приложении SQL Server Management Studio вы можете легко получить приблизительный план выполнения для любого запроса SQL, нажав сочетание клавиш CTRL+M.

enter image description here

Подробнее о получении плана выполнения при использовании SQL Server читайте в этой статье.