Wie kann ich in Microsoft SQL Server einen Ausführungsplan für eine Abfrage / gespeicherte Prozedur abrufen?
Wie kann ich in Microsoft SQL Server einen Ausführungsplan für eine Abfrage / gespeicherte Prozedur abrufen?
Antworten:
Es gibt eine Reihe von Methoden, um einen Ausführungsplan zu erhalten, die von Ihren Umständen abhängen. Normalerweise können Sie SQL Server Management Studio verwenden, um einen Plan abzurufen. Wenn Sie Ihre Abfrage jedoch aus irgendeinem Grund nicht in SQL Server Management Studio ausführen können, ist es möglicherweise hilfreich, einen Plan über SQL Server Profiler oder durch Überprüfen abzurufen der Plan-Cache.
SQL Server verfügt über einige nützliche Funktionen, mit denen Sie einen Ausführungsplan sehr einfach erfassen können. Stellen Sie einfach sicher, dass das Menüelement "Aktuellen Ausführungsplan einschließen" (im Menü "Abfrage" enthalten) aktiviert ist, und führen Sie Ihre Abfrage wie gewohnt aus .
Wenn Sie versuchen, den Ausführungsplan für Anweisungen in einer gespeicherten Prozedur abzurufen, sollten Sie die gespeicherte Prozedur wie folgt ausführen:
exec p_Example 42
Wenn Ihre Abfrage abgeschlossen ist, sollte im Ergebnisbereich eine zusätzliche Registerkarte mit dem Titel "Ausführungsplan" angezeigt werden. Wenn Sie viele Anweisungen ausgeführt haben, werden möglicherweise viele Pläne auf dieser Registerkarte angezeigt.
Von hier aus können Sie den Ausführungsplan in SQL Server Management Studio überprüfen oder mit der rechten Maustaste auf den Plan klicken und "Ausführungsplan speichern unter ..." auswählen, um den Plan in einer Datei im XML-Format zu speichern.
Diese Methode ist Methode 1 sehr ähnlich (tatsächlich ist dies das, was SQL Server Management Studio intern tut), ich habe sie jedoch der Vollständigkeit halber aufgenommen oder wenn Sie nicht über SQL Server Management Studio verfügen.
Führen Sie eine der folgenden Anweisungen aus, bevor Sie Ihre Abfrage ausführen . Die Anweisung muss die einzige Anweisung im Stapel sein, dh Sie können nicht gleichzeitig eine andere Anweisung ausführen:
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
Dies sind Verbindungsoptionen, sodass Sie diese nur einmal pro Verbindung ausführen müssen. Ab diesem Zeitpunkt werden alle ausgeführten Anweisungen von einer zusätzlichen Ergebnismenge begleitet, die Ihren Ausführungsplan im gewünschten Format enthält. Führen Sie Ihre Abfrage einfach wie gewohnt aus , um den Plan anzuzeigen .
Sobald Sie fertig sind, können Sie diese Option mit der folgenden Anweisung deaktivieren:
SET <<option>> OFF
Sofern Sie keine starke Präferenz haben, empfehle ich, die STATISTICS XML
Option zu verwenden. Diese Option entspricht der Option "Aktuellen Ausführungsplan einschließen" in SQL Server Management Studio und liefert die meisten Informationen im bequemsten Format.
SHOWPLAN_TEXT
- Zeigt einen grundlegenden textbasierten geschätzten Ausführungsplan an, ohne die Abfrage auszuführenSHOWPLAN_ALL
- Zeigt einen textbasierten geschätzten Ausführungsplan mit Kostenschätzungen an, ohne die Abfrage auszuführenSHOWPLAN_XML
- Zeigt einen XML-basierten geschätzten Ausführungsplan mit Kostenschätzungen an, ohne die Abfrage auszuführen. Dies entspricht der Option "Geschätzten Ausführungsplan anzeigen ..." in SQL Server Management Studio.STATISTICS PROFILE
- Führt die Abfrage aus und zeigt einen textbasierten tatsächlichen Ausführungsplan an.STATISTICS XML
- Führt die Abfrage aus und zeigt einen XML-basierten tatsächlichen Ausführungsplan an. Dies entspricht der Option "Aktuellen Ausführungsplan einschließen" in SQL Server Management Studio.Wenn Sie Ihre Abfrage nicht direkt ausführen können (oder wenn Ihre Abfrage nicht direkt ausgeführt wird, wenn Sie sie direkt ausführen - denken Sie daran, dass ein Plan für die Abfrage schlecht ausgeführt werden soll), können Sie einen Plan mithilfe eines SQL Server Profiler-Trace erfassen. Die Idee ist, Ihre Abfrage auszuführen, während ein Trace ausgeführt wird, der eines der "Showplan" -Ereignisse erfasst.
Beachten Sie, dass je nach Last Sie können diese Methode auf einer Produktionsumgebung verwenden, aber Sie sollten offensichtlich Vorsicht walten lassen. Die SQL Server Profilierungsmechanismen sind so konzipiert , Auswirkungen auf die Datenbank zu minimieren , aber dies bedeutet nicht , dass es nicht irgendwelche Auswirkungen auf die Leistung. Möglicherweise haben Sie auch Probleme beim Filtern und Identifizieren des richtigen Plans in Ihrer Ablaufverfolgung, wenn Ihre Datenbank stark beansprucht wird. Sie sollten sich natürlich bei Ihrem DBA erkundigen, ob er mit Ihnen in seiner wertvollen Datenbank zufrieden ist!
Der Plan, den Sie erhalten, entspricht der Option "Aktuellen Ausführungsplan einschließen" in SQL Server Management Studio.
Wenn Sie Ihre Abfrage nicht direkt ausführen können und auch keinen Profiler-Trace erfassen können, können Sie dennoch einen geschätzten Plan erhalten, indem Sie den SQL-Abfrageplan-Cache überprüfen.
Wir überprüfen den Plan-Cache, indem wir SQL Server- DMVs abfragen . Im Folgenden finden Sie eine grundlegende Abfrage, in der alle zwischengespeicherten Abfragepläne (als XML) zusammen mit ihrem SQL-Text aufgelistet werden. In den meisten Datenbanken müssen Sie außerdem zusätzliche Filterklauseln hinzufügen, um die Ergebnisse auf die Pläne zu filtern, an denen Sie interessiert sind.
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)
Führen Sie diese Abfrage aus und klicken Sie auf das Plan-XML, um den Plan in einem neuen Fenster zu öffnen. Klicken Sie mit der rechten Maustaste und wählen Sie "Ausführungsplan speichern unter ...", um den Plan in einer Datei im XML-Format zu speichern.
Da es so viele Faktoren gibt (von der Tabelle und dem Indexschema bis zu den gespeicherten Daten und den Tabellenstatistiken), sollten Sie immer versuchen, einen Ausführungsplan aus der Datenbank zu erhalten, an der Sie interessiert sind (normalerweise diejenige, bei der eine Leistung auftritt Problem).
Sie können keinen Ausführungsplan für verschlüsselte gespeicherte Prozeduren erfassen.
Ein tatsächlicher Ausführungsplan ist einer, bei dem SQL Server die Abfrage tatsächlich ausführt , während ein geschätzter Ausführungsplan SQL Server herausfindet, was er ohne Ausführung der Abfrage tun würde . Obwohl logisch äquivalent, ist ein tatsächlicher Ausführungsplan viel nützlicher, da er zusätzliche Details und Statistiken darüber enthält, was bei der Ausführung der Abfrage tatsächlich passiert ist. Dies ist wichtig, wenn Sie Probleme diagnostizieren, bei denen die Schätzungen von SQL Servern nicht korrekt sind (z. B. wenn Statistiken nicht mehr aktuell sind).
Dies ist ein Thema, das für ein (kostenloses) Buch an sich würdig genug ist .
SET STATISTICS XML ON
Setzen Sie den Anfang der Abfrage und die SET STATISTICS XML OFF|ON
umgebenden Bereiche, die nicht in der Planausgabe angezeigt werden sollen: Ich fand dies nützlich, wenn die Abfrage eine Iteration (WHILE) enthält, die Sie nicht möchten / benötigen im Ausführungsplan zu sehen (sonst wäre es zu schwer und zu lang für SQL Server, um es anzuzeigen).
Zusätzlich zu der bereits veröffentlichten umfassenden Antwort ist es manchmal nützlich, programmgesteuert auf den Ausführungsplan zugreifen zu können, um Informationen zu extrahieren. Beispielcode dafür ist unten.
DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID
StartCapture
DefinitionCREATE 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
DefinitionCREATE 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
Angenommen, Sie verwenden Microsoft SQL Server Management Studio
Neben den in den vorherigen Antworten beschriebenen Methoden können Sie auch einen kostenlosen Ausführungsplan-Viewer und ein Abfrageoptimierungstool ApexSQL Plan verwenden (auf das ich kürzlich gestoßen bin).
Sie können ApexSQL Plan installieren und in SQL Server Management Studio integrieren, sodass Ausführungspläne direkt von SSMS aus angezeigt werden können.
Anzeigen der geschätzten Ausführungspläne in ApexSQL Plan
Anzeigen der tatsächlichen Ausführungspläne in ApexSQL Plan
Um den tatsächlichen Ausführungsplan einer Abfrage anzuzeigen, fahren Sie mit dem zuvor erwähnten zweiten Schritt fort. Klicken Sie nun, sobald der geschätzte Plan angezeigt wird, in der Hauptleiste von ApexSQL Plan auf die Schaltfläche „Ist“.
Sobald Sie auf die Schaltfläche „Ist“ klicken, wird der Ist-Ausführungsplan mit einer detaillierten Vorschau der Kostenparameter zusammen mit anderen Ausführungsplandaten angezeigt.
Weitere Informationen zum Anzeigen von Ausführungsplänen finden Sie unter diesem Link .
Mein Lieblingswerkzeug zum Abrufen und gründlichen Analysieren von Abfrageausführungsplänen ist SQL Sentry Plan Explorer . Es ist viel benutzerfreundlicher, bequemer und umfassender für die Detailanalyse und Visualisierung von Ausführungsplänen als SSMS.
Hier ist ein Beispiel-Screenshot, damit Sie eine Vorstellung davon bekommen, welche Funktionen das Tool bietet:
Dies ist nur eine der im Tool verfügbaren Ansichten. Beachten Sie eine Reihe von Registerkarten am unteren Rand des App-Fensters, mit denen Sie verschiedene Arten Ihrer Ausführungsplandarstellung und nützliche zusätzliche Informationen abrufen können.
Darüber hinaus habe ich keine Einschränkungen der kostenlosen Edition festgestellt, die die tägliche Verwendung verhindern oder Sie dazu zwingen, die Pro-Version zu erwerben. Wenn Sie sich also lieber an die kostenlose Edition halten, verbietet Ihnen nichts, dies zu tun.
UPDATE: (Dank an Martin Smith ) Plan Explorer ist jetzt kostenlos! Weitere Informationen finden Sie unter http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view .
Speaking of third-party tools
als niemand Tools von Drittanbietern erwähnte.
Abfragepläne können über das query_post_execution_showplan
Ereignis aus einer Sitzung für erweiterte Ereignisse abgerufen werden . Hier ist eine XEvent-Beispielsitzung:
/*
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
Nachdem Sie die Sitzung erstellt haben, gehen Sie (in SSMS) zum Objekt-Explorer und gehen Sie zu Management | Erweiterte Ereignisse | Sitzungen. Klicken Sie mit der rechten Maustaste auf die Sitzung "GetExecutionPlan" und starten Sie sie. Klicken Sie erneut mit der rechten Maustaste darauf und wählen Sie "Live-Daten ansehen".
Öffnen Sie als Nächstes ein neues Abfragefenster und führen Sie eine oder mehrere Abfragen aus. Hier ist eine für 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
Nach ein oder zwei Augenblicken sollten auf der Registerkarte "GetExecutionPlan: Live Data" einige Ergebnisse angezeigt werden. Klicken Sie auf eines der Ereignisse query_post_execution_showplan im Raster und dann auf die Registerkarte "Abfrageplan" unter dem Raster. Es sollte ungefähr so aussehen:
EDIT : Der XEvent - Code und die Screenshot wurden von SQL / SSMS 2012 w / SP2 erzeugt. Wenn Sie SQL 2008 / R2 verwenden, können Sie das Skript möglicherweise optimieren, damit es ausgeführt wird. Da diese Version jedoch keine grafische Benutzeroberfläche hat, müssen Sie das Showplan-XML extrahieren, als * .sqlplan-Datei speichern und in SSMS öffnen. Das ist umständlich. XEvents war in SQL 2005 oder früher nicht vorhanden. Wenn Sie nicht mit SQL 2012 oder höher arbeiten, würde ich dringend eine der anderen hier veröffentlichten Antworten empfehlen.
Ab SQL Server 2016+ wurde die Query Store-Funktion eingeführt, um die Leistung zu überwachen. Es bietet Einblick in die Auswahl und Leistung des Abfrageplans. Es ist kein vollständiger Ersatz für Trace- oder erweiterte Ereignisse, aber da es sich von Version zu Version weiterentwickelt, erhalten wir möglicherweise in zukünftigen Versionen von SQL Server einen voll funktionsfähigen Abfragespeicher. Der primäre Ablauf des Abfragespeichers
Aktivieren des Abfragespeichers : Der Abfragespeicher funktioniert auf Datenbankebene auf dem Server.
tempdb
Datenbank nicht aktivieren .
sys.database_query_store_options
(Transact-SQL)
Sammeln von Informationen im Abfragespeicher : Wir erfassen alle verfügbaren Informationen aus den drei Speichern mithilfe von Query Store DMV (Data Management Views).
Abfrageplanspeicher : Behalten Sie die Ausführungsplaninformationen bei und es ist verantwortlich für die Erfassung aller Informationen, die sich auf die Abfragekompilierung beziehen.
sys.query_store_query
(Transact-SQL)sys.query_store_plan
(Transact-SQL)sys.query_store_query_text
(Transact-SQL)
Runtime Stats Store: Die Informationen zur Ausführungsstatistik bleiben erhalten und es handelt sich wahrscheinlich um den am häufigsten aktualisierten Speicher. Diese Statistiken repräsentieren Abfrageausführungsdaten.
sys.query_store_runtime_stats
(Transact-SQL)
Abfragestatistikspeicher speichern: Wartestatistikinformationen beibehalten und erfassen.
sys.query_store_wait_stats
(Transact-SQL)
ANMERKUNG: Der Abfragestatistikspeicher ist nur in SQL Server 2017+ verfügbar
Wie bei SQL Server Management Studio (bereits erläutert) ist es auch bei Datagrip möglich, wie hier erläutert .
- Klicken Sie mit der rechten Maustaste auf eine SQL-Anweisung und wählen Sie Plan erklären.
- Klicken Sie im Ausgabebereich auf Planen.
- Standardmäßig wird die Baumdarstellung der Abfrage angezeigt. Um den Abfrageplan anzuzeigen, klicken Sie auf das Symbol Visualisierung anzeigen oder drücken Sie Strg + Umschalt + Alt + U.
Hier ist eine wichtige Sache zu wissen, zusätzlich zu allem, was zuvor gesagt wurde.
Abfragepläne sind häufig zu komplex, um durch den integrierten XML- Spaltentyp dargestellt zu werden, der auf 127 Ebenen verschachtelter Elemente beschränkt ist. Dies ist einer der Gründe, warum sys.dm_exec_query_planNULL
in früheren MS SQL-Versionen möglicherweise einen Fehler zurückgibt oder sogar auslöst. Daher ist es im Allgemeinen sicherer, stattdessen sys.dm_exec_text_query_plan zu verwenden. Letzteres bietet auch eine nützliche Bonusfunktion für die Auswahl eines Plans für eine bestimmte Abrechnung anstelle der gesamten Charge. So verwenden Sie es, um Pläne für aktuell ausgeführte Anweisungen anzuzeigen:
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
Die Textspalte in der resultierenden Tabelle ist jedoch im Vergleich zu einer XML-Spalte nicht sehr praktisch. Um auf das Ergebnis zu klicken, das in einer separaten Registerkarte als Diagramm geöffnet werden soll, ohne den Inhalt in einer Datei speichern zu müssen, können Sie einen kleinen Trick verwenden (denken Sie daran, dass Sie nicht nur verwenden können CAST(... AS XML)
), obwohl dies nur für a funktioniert einzelne Reihe:
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
Wie in diesem Artikel erläutert , gibt es zwei Ausführungsplantypen, die Sie bei Verwendung von SQL Server erhalten können.
Der geschätzte Ausführungsplan wird vom Optimierer generiert, ohne die SQL-Abfrage auszuführen.
Um den geschätzten Ausführungsplan zu erhalten, müssen Sie den aktivieren SHOWPLAN_ALL
Einstellung , bevor Sie die Abfrage ausführen.
SET SHOWPLAN_ALL ON
Wenn Sie nun die folgende SQL-Abfrage ausführen:
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 generiert den folgenden geschätzten Ausführungsplan:
| 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 |
Nach dem Ausführen der Abfrage möchten wir den geschätzten Ausführungsplan abrufen. Sie müssen den deaktivieren, SHOWPLAN_ALL
da andernfalls die aktuelle Datenbanksitzung nur den geschätzten Ausführungsplan generiert, anstatt die bereitgestellten SQL-Abfragen auszuführen.
SET SHOWPLAN_ALL OFF
In der SQL Server Management Studio-Anwendung können Sie den geschätzten Ausführungsplan für jede SQL-Abfrage einfach abrufen, indem Sie auf die CTRL+L
Tastenkombination klicken.
Der eigentliche SQL-Ausführungsplan wird vom Optimierer beim Ausführen der SQL-Abfrage generiert. Wenn die Datenbanktabellenstatistiken korrekt sind, sollte der tatsächliche Plan nicht wesentlich vom geschätzten Plan abweichen.
Um den tatsächlichen Ausführungsplan für SQL Server abzurufen, müssen Sie die STATISTICS IO, TIME, PROFILE
Einstellungen aktivieren , wie im folgenden SQL-Befehl dargestellt:
SET STATISTICS IO, TIME, PROFILE ON
Wenn Sie nun die vorherige Abfrage ausführen, generiert SQL Server den folgenden Ausführungsplan:
| 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.
Nachdem Sie die Abfrage ausgeführt haben, möchten wir den tatsächlichen Ausführungsplan erhalten. Sie müssen die STATISTICS IO, TIME, PROFILE ON
Einstellungen wie folgt deaktivieren :
SET STATISTICS IO, TIME, PROFILE OFF
In der SQL Server Management Studio-Anwendung können Sie den geschätzten Ausführungsplan für jede SQL-Abfrage einfach abrufen, indem Sie auf die CTRL+M
Tastenkombination klicken.
Weitere Informationen zum Abrufen eines Ausführungsplans bei Verwendung von SQL Server finden Sie in diesem Artikel .
Sie können dies auch über Powershell mit SET STATISTICS XML ON tun, um den tatsächlichen Plan abzurufen. Ich habe es so geschrieben, dass es Pläne mit mehreren Anweisungen zu einem Plan zusammenführt.
########## 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()
Das Erklären des Ausführungsplans kann sehr detailliert sein und nimmt eine beträchtliche Lesezeit in Anspruch. Wenn Sie jedoch vor der Abfrage 'EXPLAIN' verwenden, sollten Sie viele Informationen erhalten, einschließlich der Teile, die zuerst ausgeführt wurden, und so weiter. Wenn Sie ein bisschen mehr Details dazu lesen möchten, habe ich einen kleinen Blog darüber zusammengestellt, der Sie auch auf die richtigen Refs hinweist. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470