it-swarm.com.de

Gibt es in SQL Server eine Möglichkeit, die Werte der Parameter zu ermitteln, die an eine ausführende gespeicherte Prozedur übergeben werden

Eine Möglichkeit, die ausgeführte gespeicherte Prozedur zu bestimmen, besteht darin, "dynamische Verwaltungs" -Methoden zu verwenden, wie folgt:

SELECT 
    sqlText.Text, req.* 
FROM 
    sys.dm_exec_requests req
OUTER APPLY 
    sys.dm_exec_sql_text(req.sql_handle) AS sqltext

Dies zeigt jedoch nur den Text der create-Anweisung der gespeicherten Prozedur an. z.B.:

CREATE PROCEDURE IMaProcedure @id int AS SELECT * FROM AllTheThings Where id = @id

Im Idealfall würde ich gerne sehen, welche Parameter für die laufende Prozedur verwendet wurden, die dazu führen, dass sie für den bestimmten Satz von fehlerhaften Parametern so lange ausgeführt wird.

Gibt es eine Möglichkeit, das zu tun? (In diese FrageAaron Bertrand erwähnt DBCC InputBuffer , aber ich denke nicht, dass dies für dieses Problem angemessen ist.)

13
user420667

Diese Informationen - Laufzeitparameterwerte, die an eine gespeicherte Prozedur (d. H. Einen RPC-Aufruf) oder eine parametrisierte Abfrage übergeben werden - sind nur über eine SQL-Ablaufverfolgung verfügbar (und ich nehme das entsprechende erweiterte Ereignis in den neueren Versionen von SQL Server an). Sie können dies sehen, indem Sie SQL Server Profiler (im Lieferumfang von SQL Server enthalten) ausführen und die verschiedenen Ereignisse "Abgeschlossen" auswählen, z. B.: RPC:Completed, SP:Completed, und SQL:BatchCompleted. Sie müssen auch das Feld "TextData" auswählen, da sich die Werte dort befinden.

Der Unterschied zwischen meiner Antwort und @ Kins Antwort auf diese Frage besteht darin, dass sich @ Kins Antwort (es sei denn, ich irre mich, in diesem Fall werde ich dies entfernen) darauf konzentriert, Folgendes zu erhalten:

  • Ihr eigener Abfrageplan (in diesem Fall kann er die Laufzeitparameterinformationen enthalten, jedoch nicht für andere Sitzungen/SPIDs), oder
  • pläne aus den DMVs (in diesem Fall haben sie sollte nur die kompilierten Parameterwerte, die keine Laufzeitwerte sind).

Meine Antwort konzentriert sich darauf, die Parameterwerte für andere Sitzungen abzurufen, die gerade ausgeführt werden. Wenn Sie sich auf die DMVs verlassen, können Sie nicht feststellen, ob der Laufzeitparameterwert mit dem kompilierten Parameterwert übereinstimmt. Der Kontext dieser Frage besteht darin, den Laufzeitwert von Abfragen zu ermitteln, die über andere Sitzungen/SPIDs (und in SQL Server 2005, während erweiterte Ereignisse in SQL Server 2008 eingeführt wurden) gesendet wurden.

16
Solomon Rutzky

Sie können den tatsächlichen Ausführungsplan aktivieren und dann das XML des Ausführungsplans anzeigen.

(enter image description here

Oder Sie können Plan-Explorer-Tool von sql sentry verwenden und die Registerkarte parameters anzeigen, auf der die compiled value Und run time value Für den tatsächlichen Ausführungsplan aufgelistet sind.

Wenn Sie den tatsächlichen Plan nicht aktivieren können, können Sie wie unten beschrieben in den Plan-Cache schauen.

-- borrowed from  Erland Sommarskog
-- Link : http://www.sommarskog.se/query-plan-mysteries.html#dmvgettingplans
-- Remember that you are looking at the estimated plan so the actual no. of rows and actual executions wont be there ! <-- Important why a particular plan is bad.

DECLARE @dbname    nvarchar(256),
        @procname  nvarchar(256)
SELECT @dbname = 'Northwind',  -- Your DB name
       @procname = 'dbo.List_orders_11' -- The SP that you want to get parameters for !

; WITH basedata AS (
   SELECT qs.statement_start_offset/2 AS stmt_start,
          qs.statement_end_offset/2 AS stmt_end,
          est.encrypted AS isencrypted, est.text AS sqltext,
          epa.value AS set_options, qp.query_plan,
          charindex('<ParameterList>', qp.query_plan) + len('<ParameterList>')
             AS paramstart,
          charindex('</ParameterList>', qp.query_plan) AS paramend
   FROM   sys.dm_exec_query_stats qs
   CROSS  APPLY sys.dm_exec_sql_text(qs.sql_handle) est
   CROSS  APPLY sys.dm_exec_text_query_plan(qs.plan_handle,
                                            qs.statement_start_offset,
                                            qs.statement_end_offset) qp
   CROSS  APPLY sys.dm_exec_plan_attributes(qs.plan_handle) epa
   WHERE  est.objectid  = object_id (@procname)
     AND  est.dbid      = db_id(@dbname)
     AND  epa.attribute = 'set_options'
), next_level AS (
   SELECT stmt_start, set_options, query_plan,
          CASE WHEN isencrypted = 1 THEN '-- ENCRYPTED'
               WHEN stmt_start >= 0
               THEN substring(sqltext, stmt_start + 1,
                              CASE stmt_end
                                   WHEN 0 THEN datalength(sqltext)
                                   ELSE stmt_end - stmt_start + 1
                              END)
          END AS Statement,
          CASE WHEN paramend > paramstart
               THEN CAST (substring(query_plan, paramstart,
                                   paramend - paramstart) AS xml)
          END AS params
   FROM   basedata
)
SELECT set_options AS [SET], n.stmt_start AS Pos, n.Statement,
       CR.c.value('@Column', 'nvarchar(128)') AS Parameter,
       CR.c.value('@ParameterCompiledValue', 'nvarchar(128)') AS [Sniffed Value],
       CAST (query_plan AS xml) AS [Query plan]
FROM   next_level n
CROSS  APPLY   n.params.nodes('ColumnReference') AS CR(c)
ORDER  BY n.set_options, n.stmt_start, Parameter
13
Kin Shah

@SolomonRutzky ist richtig.
SQL Profiler Trace ist der einzige Weg (, ohne den Sproc zu bearbeiten ).

Bearbeiten Sie Ihren Sproc:

Jedoch ist es das nächstbeste, den fraglichen Sproc leicht zu bearbeiten.
Deklarieren Sie eine DateTime-Variable am Anfang mit der aktuellen Uhrzeit.
Protokollieren Sie am Ende des Sproc die Werte für Sproc_StartTime, Sproc_EndTime und Parameter in einer Tabelle.

Sie können sogar eine bedingte Logik hinzufügen, um ein DateDiff () nur für die Protokollierung zu verwenden, wenn für die Verarbeitung des Sproc eine längere Zeit verwendet wurde.
Dies kann Ihren Sproc beschleunigen und den Speicherplatzverbrauch Ihrer Protokolltabelle verringern, wenn der Sproc auf dem neuesten Stand ist.

Dann haben Sie eine Protokolldatei, die Sie über Monate abfragen und analysieren können (ohne dass ein Trace in Prod ausgeführt wird).
Wenn Sie mit dem Einstellen Ihres Sproc fertig sind, löschen Sie einfach die wenigen Zeilen der Timer- und Logger-Logik, die Sie hinzugefügt haben.

Cache-Plan-Parameterwerte:

Ich sollte erwähnen, dass das Einbeziehen der aktuellen Cached-Plan-Parameterwerte in Ihre Protokolltabelle Ihnen dabei helfen kann, festzustellen, ob sie das Leistungsproblem verschärfen.
Ich benutze OPTIMIZE FOR, um festzulegen, wie mit Parametern in meinem Sproc umgegangen werden soll, wenn ich weiß, dass sie zum Schneiden und Schneiden von Daten verwendet werden.
Ich finde das mit OPTIMIZE FOR liefert konsistente und schnelle Ergebnisse, wenn derselbe Sproc mit Parametern wie optionale Filter verwendet wird.
Es ist definitiv eine Variable weniger zu berücksichtigen, wenn Sie angeben, wie mit ihnen umgegangen werden soll.

Unten finden Sie ein Beispiel dafür, was Sie am Ende Ihrer Select-Anweisung hinzufügen könnten:

OPTION(OPTIMIZE FOR (@SiteID = 'ABC',
                     @LocationID = NULL, @DepartmentID = NULL,
                     @EmployeeID = NULL, @CustomerID = NULL,
                     @ProductID = NULL, @OrderID = NULL, @OrderStatusID = NULL,
                     @IncludedCancelledOrders = 1,
                     @StartDate UNKNOWN, @EndDate UNKNOWN))
1
MikeTeeVee

Bei der Verwendung der Abfrage von Erland Sommarskog zum Vernichten von Plan-XML und zum Abrufen von ParameterCompiledValue ist mir aufgefallen, dass der erste CTE "basedata" keine Pläne berücksichtigt, die WARNUNGEN (z. B. implizit) enthalten Konvertierungen), da der CHARINDEX (integrierte Funktion) nach dem ersten Ausdruck sucht, der mit der Zeichenfolgeneingabe (dh) übereinstimmt, und solche Warnungen dieselben Phrasen/Knoten verwenden.

Ich schlage daher vor, diesen Abschnitt durch den folgenden überarbeiteten Abschnitt zu ersetzen:

      CHARINDEX('<ParameterList>', qp.query_plan) + LEN('<ParameterList>') AS paramstart,
      CHARINDEX('</ParameterList>', qp.query_plan) AS paramend

Überarbeiteter Abschnitt :

       CHARINDEX('<ParameterList><ColumnReference', qp.query_plan) + LEN('<ParameterList>') AS paramstart,
       CHARINDEX('</ParameterList></QueryPlan>', qp.query_plan) AS paramend
0
SQLcyclopedia