SQL Server'da, çalıştırılan bir saklı yordama geçirilen parametrelerin değerlerini belirlemenin bir yolu var mı?


13

Saklı yordamı yürütmenin bir yolu, "dinamik yönetim" yöntemlerini kullanmaktır, şöyle:

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

Ancak, bu yalnızca saklı yordamın create deyiminin metnini görüntüler. Örneğin:

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

İdeal olarak, belirli rahatsız edici parametreler kümesi için çok uzun süre çalışmasına neden olan çalıştırma prosedürü için parametrelerin ne olduğunu görmek istiyorum.

Bunu yapmanın bir yolu var mı? ( Bu soruda Aaron Bertrand DBCC InputBuffer'dan bahsediyor , ancak bunun bu sorun için uygun olduğunu düşünmüyorum.)


Gerçekten giriş parametrelerini yakalamanın veya çalışma zamanında nelerin geçtiğini görmenin tek yolu, değerleri ve bir günlük dosyasına yapılan çağrıyı kaydetmektir. Hata günlüğünde görmek veya biraz daha fazla çaba sarf etmek istiyorsanız, RAISEERROR ile bunu kolayca yapabilirsiniz.
Steve Mangiameli

Yanıtlar:


16

Bu bilgiler - bir Saklı Yordam (yani RPC çağrısı) veya parametreli sorguya geçirilen çalışma zamanı parametre değerleri - yalnızca bir SQL İzlemesi ile kullanılabilir (ve SQL Server'ın yeni sürümlerinde eşdeğer Genişletilmiş Olay olduğunu varsayalım). : Sen (o SQL Server ile birlikte gelen), SQL Server Profiler çalışan ve gibi çeşitli "Tamamlandı" olayları, seçerek görebilirsiniz RPC:Completed, SP:Completedve SQL:BatchCompleted. Değerler orada olacağından "TextData" alanını da seçmeniz gerekir.

Cevabım arasında Kin adlı @ fark cevap bu Sorunu üzerine (ı yanlış sürece, bu durumda bu kaldıracaktır) Kin cevabı @ ya sağlamaya odaklanan olmasıdır:

  • kendi sorgu planınız (bu durumda çalışma zamanı parametre bilgisine sahip olabilir, ancak diğer Oturumlar / SPID'ler için olmayabilir) veya
  • DMV'lerden planlar (bu durumda , yalnızca çalışma zamanı değerleri olmayan derlenmiş parametre değerlerine sahip olmalıdırlar ).

Cevabım , şu anda çalışmakta olan diğer oturumların parametre değerlerini almaya odaklanır . DMV'lere güvenirken, çalışma zamanı parametre değerinin derlenmiş parametre değeri ile aynı olup olmadığını bilmenin bir yolu yoktur. Ve bu sorunun bağlamı, diğer Oturumlar / SPID'ler (ve SQL Server 2005'te gönderilirken sorguların çalışma zamanı değerini izlerken Genişletilmiş Olaylar SQL Server 2008'de tanıtıldı).


13

Sen edebilirsiniz gerçek yürütme planı açmak ve icra planı XML bakmak sonra.

resim açıklamasını buraya girin

Yoksa kullanabilirsiniz sql Nöbetçinin planı kaşif aracı ve görün parameterslisteler sekmesini compiled valueve run time valuefiili yürütme planı için.

Eğer değilse olamaz gerçek planı açmak aşağıda açıklandığı gibi o zaman planı önbelleğine bakabilirsiniz.

-- 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

5
Plan önbelleği, daha sonra belirli bir çalıştırmanın değerleri yerine yalnızca derlenmiş değerlere sahiptir. Showplan XML Statistics ProfileProfiler'deki etkinliği kullanmak için Profiler'deki etkinliği kullanmak da mümkün olabilir.
Martin Smith

1

@SolomonRutzky haklı.
SQL Profiler Trace ( Sproc'u düzenlemeden ) tek yoldur .

Sproc Düzenleyin:

Ancak , bir sonraki en iyi şey söz konusu Sproc'u hafifçe düzenlemektir.
Geçerli Saat ile başlangıçta bir DateTime değişkeni bildirin.
Sproc Sonunda, Sproc_StartTime, Sproc_EndTime ve Parametre Değerlerini Tabloya Kaydedin.

DateDiff () işlevini kullanmak için, yalnızca Sproc'un işlenmesinde uzun bir süre kullanıldığında günlüğe kaydetmek için bazı koşullu mantık bile ekleyebilirsiniz.
Bu, Sproc'unuzu hızlandırabilir ve Sproc'un uç üstü çalıştığı zamanlar için Günlük Tablonuzun Alan Tüketimini azaltabilir.

Ardından, aylar içinde sorgulayabileceğiniz ve analiz edebileceğiniz bir Günlük Dosyanız var (Prod'da çalışan bir İzleme olmadan).
Sproc'unuzu ayarlamayı tamamladığınızda, eklediğiniz birkaç Timer ve Logger mantığını silin.

Önbellekli Plan Parametre Değerleri:

Günlük Önbelleğinize Geçerli Önbelleğe Alınmış Plan Parametre Değerlerini eklemenin , performans sorununu birleştirip birleştirmediklerini belirlemenize yardımcı olabileceğini belirtmeliyim . Verileri dilimlemek ve küp şeklinde kesmek için kullanılacağını bildiğimde Sproc'umdaki Parametrelerin nasıl ele alınacağını ayarlamak için
kullanıyorum OPTIMIZE FOR. İsteğe Bağlı Filtreler ile aynı Sproc parametrelerini kullanırken tutarlı ve hızlı sonuçlar elde edilmesini
buluyorum . Onlarla nasıl başa çıkacağınızı belirtmeniz kesinlikle daha az değişkendir.OPTIMIZE FOR

Aşağıda, Seçim İfadenizin altına ekleyebileceğiniz öğelerin bir örneği verilmiştir:

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))

0

Plan XML'i parçalamak ve ilk "basedata" CTE'sinin UYARILAR (örn. Örtük dönüşümler) ilk ifade eşleme dizesini arar gibi planları hesaba katmadığını ParameterCompiledValue çıkarmak için Erland Sommarskog sorgusu kullanırken fark ettim girdi (yani) ve bu tür uyarılar aynı ifadeleri / düğümleri kullanır.

Bu nedenle, bu bölümün aşağıdaki revize edilmiş bölüm ile değiştirilmesini öneriyorum:

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

Gözden Geçirilmiş Bölüm:

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

Disallowed implicit conversion from data type xml to data type varchar, table 'sys.dm_exec_query_plan', column 'query_plan'. Use the CONVERT function to run this query.
Matt

-1
SELECT DB_NAME(req.database_id),
sqltext.TEXT,
req.session_id,
req.status,
req.start_time,
req.command,
req.cpu_time,
req.total_elapsed_time ,   REPLACE(REPLACE(REPLACE(REPLACE(
CONVERT(VARCHAR(MAX), CONVERT(XML, REPLACE( query_plan, 'xmlns="','xmlns1="')).query('//        ParameterList/ColumnReference')),
'<ColumnReference Column="','declare '),
'" ParameterDataType="',' '),
'" ParameterCompiledValue="(',' = '),
')"/>', CONCAT(';', CHAR(10) , CHAR(13))) ParameterList
FROM sys.dm_exec_requests req
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext 
 CROSS  APPLY sys.dm_exec_text_query_plan(plan_handle, statement_start_offset, statement_end_offset) qp
order by req.total_elapsed_time desc 

2
Yalnızca kod yanıtları önerilmez. Bu kodun neden bir sorunu çözdüğüne ilişkin bir açıklama ekleyin. Bkz Cevap Nasıl
Peter Vandivier
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.