Wann wird ein Ausführungsplan in sp_WhoIsActive nicht angezeigt?

8

Ich verwende das hervorragende sp_WhoIsActiveVerfahren von Adam Machanic , um Aktivitäten anzuzeigen und mich in einer Tabelle anzumelden, um lang laufende Abfragen zu beheben .

Warum wird der Ausführungsplan nicht immer in den Ergebnissen angezeigt? Meistens ist der query_planWert NULL. Wenn ich mir die SQL_TEXTSpalte in den Ergebnissen ansehe, sehe ich die Abfrage mit Parametern, aber ohne Werte, wie unten:

(@P0 nvarchar(4000),@P1 nvarchar(4000))
select blah from foo where a = @P0 and b = @P1 

Wie erhalte ich die Ausführungspläne, wenn sie hier nicht angezeigt werden? Warum werden sie nicht angezeigt? Muss ich Profiler oder Extended Events verwenden? Würde das Einfügen von Dummy-Werten in diese Parameter und das Ausführen der Abfrage mit dem tatsächlich enthaltenen Ausführungsplan denselben Plan erzeugen, der tatsächlich bei der Protokollierung verwendet wurde?

Ich habe beim Anbieter überprüft, dass er Hibernate 3.5 verwendet.

Irgendein Typ
quelle

Antworten:

10

Wie erhalte ich die Ausführungspläne, wenn sie hier nicht angezeigt werden?

Eine Möglichkeit könnte darin bestehen, plan_handleden Abfrageplan zu erfassen und anschließend plan_handlemit der folgenden Abfrage nachzuschlagen:

SELECT CONVERT(XML, query_plan) from sys.dm_exec_text_query_plan(
    0x0600050059E32C0/*Truncated for brevity, replace with your full plan_handle*/,
    DEFAULT,
    DEFAULT
)

Sie können plan_handledie Abfrage mithilfe der Abfrage im folgenden Reason #1Abschnitt erfassen oder eine kleine Änderung vornehmen sp_whoisactive, um sie in den Ergebnissen anzuzeigen. (Es ist bereits in der Zwischentabelle erfasst, die in #sessionsverwendet wird sp_whoisactive).

In jedem Fall, in dem ich einen NULLAbfrageplan beobachtet habe , war der Abfrageplan kurz danach (in allen Fällen <1 Sekunde) über diese Methode verfügbar.

Würde das Einfügen von Dummy-Werten in diese Parameter und das Ausführen der Abfrage mit dem tatsächlich enthaltenen Ausführungsplan denselben Plan erzeugen, der tatsächlich bei der Protokollierung verwendet wurde?

Auf diese Weise erhalten Sie eine Vorstellung davon, wie der Plan aussehen könnte. Wenn die RetrievedFromCacheEigenschaft des Abfrageplans lautet true, wird höchstwahrscheinlich derselbe Plan angezeigt, der verwendet wurde.

Warum werden die Abfragepläne nicht in sp_whoisactive angezeigt?

Es gibt zumindest einige mögliche Gründe, warum ein Plan möglicherweise nicht angezeigt wird, aber ich habe dies nicht mit der von Ihnen gemeldeten Häufigkeit beobachtet, und es wird interessant sein, andere Antworten zu sehen, die die Lücken füllen.

Grund Nr. 1: sys.dm_exec_requests meldet einen Anweisungstartversatz von -1

Schauen wir uns zunächst eine vereinfachte Version des Abschnitts an sp_whoisactive, in dem Abfragepläne nachgeschlagen werden:

SELECT t.text,
    r.plan_handle,
    r.statement_start_offset,
    r.statement_end_offset,
    query_plan = (
        SELECT CONVERT(xml, query_plan)
        FROM sys.dm_exec_text_query_plan (
            r.plan_handle, 
            r.statement_start_offset,
            r.statement_end_offset
        )
    )
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_requests r
    ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1

Und hier ist ein Beispielergebnis von meinem Server:

Geben Sie hier die Bildbeschreibung ein

Basierend auf der Dokumentation scheint es nicht so, als wäre -1 ein erwarteter Wert für sys.dm_exec_requests.statement_start_offset. Es scheint jedoch etwas häufig zu sein, und das sp_whoisactiveVerfahren unternimmt keinen Versuch, mit dieser Situation umzugehen.

Bei meinen Tests bin ich mir nicht einmal sicher, ob dies möglich wäre. Selbst beim Aufrufen sys.dm_exec_text_query_planmit den Standardwerten (um den gesamten Plan zu finden, nicht den spezifischen Plan basierend auf dem Versatz) stellte ich fest, dass kein Plan bereitgestellt wurde, wenn sys.dm_exec_requests.statement_start_offset-1 war.

Ich denke, es besteht die Möglichkeit einer Situation, in der die Anfrage existiert, aber der Plan und der aktuelle Kontoauszugsoffset noch nicht verfügbar sind. Ich kenne jedoch nicht die vollständige Erklärung für dieses Verhalten. Da a plan_handleverfügbar ist (zumindest in meinen Fällen mit einem NULLPlan), glaube ich nicht, dass die Planerstellung noch stattfindet.

Grund Nr. 2: Das Auffinden des Abfrageplans dauerte mehr als 5 ms

Bei der vollständigen Implementierung von wird sp_whoisactivetatsächlich ein Cursor verwendet, um jeden Plan einzeln nachzuschlagen. Es ist ein LOCK_TIMEOUTvon 5mszu vermeiden , das gesamte Verfahren zu verzögern zu viel im Falle einer Sperre auf, wenn eine bestimmte Plan aufzublicken.

--Wait up to 5 ms for the SQL text, then give up
SET LOCK_TIMEOUT 5;
WHILE @@FETCH_STATUS = 0
...

In diesem Fall sp_whoisactivesollte die Ausgabe für jedoch <timeout_exceeded />im query_planFeld angezeigt werden. Ich habe dies einige Male gesehen, daher denke ich, dass ein NULLWert in Ihrem Fall eher der Grund Nr. 1 ist.

Grund Nr. 3: Das XML des Abfrageplans ist zu komplex

Dies erscheint in Ihrem Fall nicht wahrscheinlich, wenn der Abfragetext so einfach ist wie Ihr Beispiel. Es besteht jedoch auch die Möglichkeit, dass ein NULLAbfrageplan angezeigt wird, da XML zu komplex ist.

Beim Durchsehen sp_whoisactivesieht es jedoch so aus, als würde dieser Fall mit einer Nachricht Could not render showplan due to XML data type limitations.und Anweisungen zum Konvertieren des unformatierten XML in eine .sqlplan-Datei behandelt.

Geoff Patterson
quelle