Як отримати план виконання запитів на SQL сервері?


338

Як в Microsoft SQL Server можна отримати план виконання запиту для запиту / збереженої процедури?


2
Як закрити вкладку "План виконання" в студії управління сервером SQL?
Пол Маккарті

2
@Paul Ви можете натиснути Ctrl + R для цього. Він закриває весь розділ результатів - включаючи повідомлення та план виконання.
Нісарг

Відповіді:


501

Існує ряд методів отримання плану виконання, який використовуватимуть залежно від ваших обставин. Зазвичай ви можете використовувати студію управління SQL Server для отримання плану, однак якщо з якихось причин ви не можете запустити свій запит у SQL Server Management Studio, то вам може бути корисним отримати план через Profiler SQL Server або перевірити кеш плану.

Спосіб 1 - Використання студії управління SQL Server

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

Включіть пункт меню "План виконання дій"

Якщо ви намагаєтеся отримати план виконання для операторів у збереженій процедурі, вам слід виконати збережену процедуру, наприклад:

exec p_Example 42

Після завершення запиту на панелі результатів відобразиться додаткова вкладка під назвою "План виконання". Якщо ви запустили багато заяв, то на цій вкладці може відображатися багато планів.

Скріншот плану виконання

Звідси ви можете ознайомитись із планом виконання у студії управління SQL Server або клацніть правою кнопкою миші та виберіть "Зберегти план виконання як ...", щоб зберегти план у файлі у форматі XML.

Спосіб 2 - Використання параметрів SHOWPLAN

Цей метод дуже схожий на метод 1 (насправді це те, що SQL Server Management Studio робить всередині), проте я включив його для повноти або якщо у вас немає студії управління SQL Server.

Перш ніж запустити запит, запустіть одне із наведених нижче тверджень. Оператор повинен бути єдиним твердженням у пакеті, тобто ви не можете виконати інший оператор одночасно:

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 і надає найбільшу інформацію в найбільш зручному форматі.

  • SHOWPLAN_TEXT - Відображає базовий текстовий орієнтовний план виконання, не виконуючи запит
  • SHOWPLAN_ALL - Відображає текстовий орієнтовний план виконання з оцінкою витрат, не виконуючи запит
  • SHOWPLAN_XML- Відображає орієнтовний план виконання на основі XML з оцінкою витрат, не виконуючи запит. Це еквівалентно параметру "Відображати передбачуваний план виконання ..." в студії управління SQL Server.
  • STATISTICS PROFILE - Виконує запит і відображає текстовий фактичний план виконання.
  • STATISTICS XML- Виконує запит і відображає фактичний план виконання на основі XML. Це еквівалентно опції "Включити фактичний план виконання" в студії управління SQL Server.

Спосіб 3 - Використання профіля SQL Server

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

Зауважте, що залежно від навантаження ви можете використовувати цей метод у виробничих умовах, однак, очевидно, слід бути обережними. Механізми профілювання SQL Server розроблені для мінімізації впливу на базу даних, але це не означає, що ніякого впливу на продуктивність не буде . Також у вас можуть виникнути проблеми з фільтрацією та виявленням правильного плану у вашому сліді, якщо ваша база даних не використовується. Ви, очевидно, повинні проконсультуватися у своєї DBA, щоб побачити, чи задоволені вони від вас, роблячи це на своїй дорогоцінній базі даних!

  1. Відкрийте програму SQL Server Profiler і створіть новий слід, підключившись до потрібної бази даних, до якої потрібно записати трасування.
  2. На вкладці "Вибір подій" встановіть прапорець "Показати всі події", встановіть прапорець "Ефективність" -> "Показати XML" та запустіть трасування.
  3. Поки слід прослідковується, виконайте все, що вам потрібно, щоб запустити повільно запущений запит.
  4. Зачекайте, коли запит завершиться і зупинить слід.
  5. Щоб зберегти трасування, клацніть правою кнопкою миші на план xml у програмі SQL Server Profiler та виберіть "Витягнути дані подій ...", щоб зберегти план у файлі у форматі XML.

Отриманий вами план еквівалентний опції "Включити фактичний план виконання" в студії управління SQL Server.

Спосіб 4 - Перевірка кешу запитів

Якщо ви не можете запустити запит безпосередньо, а також не можете зафіксувати слід профілера, тоді ви все одно можете отримати приблизний план, перевіривши кеш плану плану запитів SQL.

Ми перевіряємо кеш плану, запитуючи DMV SQL Server . Далі наведено базовий запит, який перелічить усі кешовані плани запитів (у вигляді 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-серверів вимкнено (наприклад, коли застаріла статистика).

Як інтерпретувати план виконання запиту?

Це досить гідна тема (безкоштовно) книги .

Дивись також:


8
Примітка для майбутніх читачів: покладіть SET STATISTICS XML ONмурашник на початок запиту, а також SET STATISTICS XML OFF|ONнавколишні області, які ви не хочете відображати у плані виводу: я вважаю це корисним, коли запит містить ітерацію (WHILE), яку ви не хочете / не потребуєте бачити в плані виконання (інакше SQL SERVER би відображав його занадто важко і довго).
Роймер

2
@MonsterMMORPG ви можете скористатися методом 4, а потім виберіть його. Наприклад, за допомогою <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </… > connection.Query <string> ("SELECT query_plan FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text plan" ) CROSS APPLY sys.dm_exec_query_plan (plan_handle) WHERE TEXT LIKE N '% Ваш оригінальний запит йде тут%' "); % S є, якщо ви використовуєте лише підмножину запиту.
позначки

2
@Justin Друге видання книги, до якої ви посилаєтесь, для інтерпретації плану виконання запитів, датується 2009 роком. Чи все-таки ви б сказали, що це справді хороший ресурс для цієї мети у 2016 році?
Абдул

3
@Abdul У того ж автора, Гранта Фрітчі, є новіша книга, яка називається Налаштування продуктивності запитів SQL Server, яка охоплює новіші версії SQL Server.
thelem

42

На додаток до вже викладеної вичерпної відповіді, іноді корисно мати доступ до плану виконання програмно для отримання інформації. Приклад коду для цього наведено нижче.

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

18

Припустимо, що ви використовуєте Microsoft SQL Server Management Studio

  • Для плану розрахункового запиту можна натиснути Ctrl + L або наступну кнопку.

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

  • Для фактичного плану запитів ви можете натиснути Ctrl + M або наступну кнопку перед виконанням запиту.

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

  • Для плану запитів наживо (лише в SSMS 2016) перед виконанням запиту використовуйте наступну кнопку.

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


15

Окрім методів, описаних у попередніх відповідях, ви також можете скористатися вільним переглядачем плану виконання та інструментом оптимізації запитів ApexSQL Plan (на який я нещодавно натрапив).

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

Перегляд передбачуваних планів виконання в плані ApexSQL

  1. Натисніть кнопку Новий запит у SSMS та вставте текст запиту у вікно тексту запиту. Клацніть правою кнопкою миші та виберіть у контекстному меню опцію "Відобразити передбачуваний план виконання".

Нова кнопка запитів у SSMS

  1. Діаграми плану виконання будуть показані на вкладці План виконання у розділі результатів. Далі клацніть правою кнопкою миші план виконання і в контекстному меню виберіть параметр «Відкрити в плані ApexSQL».

План виконання

  1. Розрахунковий план виконання буде відкрито в плані ApexSQL і його можна буде проаналізувати для оптимізації запитів.

Розрахунковий план виконання

Перегляд фактичних планів виконання у плані ApexSQL

Щоб переглянути фактичний план виконання запиту, перейдіть з 2-го кроку, згаданого раніше, але тепер, коли буде показано прогнозований план, натисніть кнопку «Фактичний» на головній стрічці в плані ApexSQL.

натисніть кнопку "Актуально" на головній смузі стрічки

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

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

Більше інформації про перегляд планів виконання можна отримати за цим посиланням .


14

Моїм улюбленим інструментом для отримання та глибокого аналізу планів виконання запитів є SQL Sentry Plan Explorer . Це набагато більш зручний для користувачів, зручний та всебічний для детального аналізу та візуалізації планів виконання, ніж SSMS.

Ось зразковий знімок екрана, щоб ви мали уявлення про те, яку функціональність пропонує інструмент:

Знімок екрана вікна провідника плану SQL Sentry Plan Explorer

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

Крім того, я не помітив жодних обмежень його безкоштовного видання, що заважає використовувати його щодня або змушує вас купувати Pro версію. Отже, якщо ви віддаєте перевагу дотримуватися безкоштовного видання, ніщо не забороняє вам цього робити.

ОНОВЛЕННЯ: (Завдяки Мартіну Сміту ) План Explorer зараз безкоштовний! Докладні відомості див. У розділі http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view .


1
Хто говорив про сторонні інструменти?
Башер

12
@basher: ОП не обмежував засоби засобами MS чи ще якось. Тож, чому ви вважаєте, що відповідь, що стосується стороннього інструменту, є невідповідною?
Олександр Абакумов

3
Просто жартував навколо того, як ви формулювали початок своєї відповіді, Speaking of third-party toolsколи ніхто не згадував інструменти сторонніх виробників.
башер

4
@basher: О, приємний улов! Дякую! Я переписав свою відповідь. Будь ласка, не соромтеся надіслати відгук та / або оновити його, якщо хочете.
Олександр Абакумов

3
До речі, зараз є лише одна версія sqlsentry.com/products/plan-explorer/sql-server-query-view
Мартін Сміт

7

Плани запитів можна отримати з розширеного сеансу подій через 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 у сітці, а потім натисніть на вкладку "План запитів" під сіткою. Це має виглядати приблизно так:

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

EDIT : Код XEvent і знімки екрану були отримані від SQL / SSMS 2012 Вт / SP2. Якщо ви використовуєте SQL 2008 / R2, можливо , ви зможете налаштувати сценарій, щоб він запустився. Але ця версія не має графічного інтерфейсу, тому вам доведеться витягти XML showplan, зберегти його як * .sqlplan файл і відкрити його в SSMS. Це громіздко. XEvents не існувало в SQL 2005 або раніше. Отже, якщо ви не на SQL 2012 або пізнішої версії, я настійно пропоную один з інших відповідей, розміщених тут.


5

Починаючи з SQL Server 2016+, для контролю продуктивності була введена функція магазину запитів. Він дає змогу ознайомитись із вибором та роботою плану запитів. Це не повна заміна слідів або розширених подій, але в міру того, як вона розвивається від версії до версії, ми можемо отримати повністю функціональний магазин запитів у майбутніх випусках від SQL Server. Первинний потік магазину запитів

  1. Існуючі компоненти SQL Server взаємодіють із магазином запитів за допомогою диспетчера магазинів запитів.
  2. Менеджер магазинів запитів визначає, який магазин потрібно використовувати, а потім передає виконання в цей магазин (Статистика плану або програми виконання або Статистика очікування запиту)
    • План магазину - збереження інформації про план виконання
    • Магазин статистики виконання - збереження інформації про статистику виконання
    • Магазин статистики очікування запитів - зберігається інформація про статистику очікування.
  3. Статистика, програма виконання та магазин Wait використовує магазин запитів як розширення до SQL Server.

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

  1. Включення магазину запитів : Магазин запитів працює на рівні бази даних на сервері.

    • Магазин запитів за замовчуванням не активний для нових баз даних.
    • Ви не можете ввімкнути сховище запитів для майстра або tempdbбази даних.
    • Доступний DMV

      sys.database_query_store_options (Transact-SQL)

  2. Збір інформації в магазині запитів : ми збираємо всю наявну інформацію з трьох магазинів, використовуючи DMV Store Store (Перегляд даних).

    • Магазин плану запитів: зберігається інформація про план виконання, і він підзвітний за фіксацію всієї інформації, яка пов'язана зі складанням запитів.

      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)

    • Магазин статистики очікування запитів: зберігається та фіксується інформація про статистику очікування.

      sys.query_store_wait_stats (Transact-SQL)

ПРИМІТКА: Магазин статистики очікування запитів доступний лише у SQL Server 2017+


4

Як і у студії управління SQL Server (вже пояснено), це можливо також із Datagrip, як пояснено тут .

  1. Клацніть правою кнопкою миші оператор SQL та виберіть Пояснити план.
  2. На панелі "Виведення" натисніть "План".
  3. За замовчуванням ви бачите дерево представлення запиту. Щоб переглянути план запитів, натисніть значок Показати візуалізацію або натисніть Ctrl + Shift + Alt + U

3

Ось одне важливе, що потрібно знати, окрім всього сказаного раніше.

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

3

Ви також можете зробити це через посібник, використовуючи 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()

2

Як я пояснив у цій статті , є два типи плану виконання, які ви можете отримати при використанні SQL Server.

Розрахунковий план виконання

Орієнтовний план виконання генерується оптимізатором без запуску запиту SQL.

Для того, щоб отримати орієнтовний план виконання, вам слід включити SHOWPLAN_ALLналаштування перед виконанням запиту.

УВІМКНЕНО SHOWPLAN_ALL

Тепер, виконуючи наступний запит 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клавішу швидкого доступу.

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

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

Фактичний план виконання 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клавішу швидкого доступу.

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

Детальніше про отримання плану виконання під час використання SQL Server див. У цій статті .


0

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.