Posso ottenere SSMS per mostrarmi i costi della query effettiva nel riquadro del piano di esecuzione?


8

Sto risolvendo problemi di prestazioni su una procedura memorizzata multistatement in SQL Server. Voglio sapere su quali parti dovrei trascorrere del tempo.

Capisco da Come posso leggere il costo della query ed è sempre una percentuale? che anche quando viene detto a SSMS di includere il piano di esecuzione effettivo , le cifre "Costo query (relativo al batch)" sono ancora basate su stime dei costi , che possono essere molto lontane dagli effettivi

Comprendo dalla misurazione delle prestazioni della query: "Costo della query del piano di esecuzione" vs "Tempo impiegato" che posso racchiudere l'invocazione della procedura memorizzata con le SET STATISTICS TIMEistruzioni e quindi otterrò un elenco come questo nel Messagesriquadro:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 1 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

[etc]

 SQL Server Execution Times:
   CPU time = 187 ms,  elapsed time = 206 ms.

con un messaggio di output per ogni istruzione.

Posso "facilmente" (anche se non convenientemente) associare l'output delle statistiche temporali ai piani di esecuzione istruzione per istruzione nel riquadro del piano di esecuzione, contandoli: l' SQL Server Execution Timesoutput del quarto messaggio corrisponde a Query 4nel riquadro del piano di esecuzione e così via.

Ma c'è un modo migliore?

Risposte:


8

Non conosco un modo per farlo nel piano di Management Studio, ma questa è una delle tante cose che Explorer Plan gratuito SentryOne farà per te quando genererai un piano reale all'interno dello strumento - include tutti i metriche di runtime per istruzione.


Wow, sembra grandioso. Basta quindi sono sicuro, le Duratione CPUrisultati colonne sono effettivi piuttosto che preventivi, sì?
AakashM,

@AakashM sì, quelli sono reali.
Aaron Bertrand

5

Un buon modo per farlo è con Profiler. Imposta una "riprogrammazione" del tuo problema proc su un box di sviluppo o test, ovvero una chiamata di esempio al proc con parametri. Quindi, utilizzando Profiler, crea una traccia utilizzando il modello TSQL_SPs o da un modello vuoto, aggiungi l'evento SP: StmtCompleted. Aggiungi le colonne Durata, Letture, Scritture e CPU se non sono già disponibili. Aggiungi un filtro alla traccia sul tuo SPID (che dovresti conoscere da Management Studio). È inoltre possibile aggiungere un filtro a Durata (ad esempio maggiore di 1000 = maggiore di 1 secondo).

È possibile eseguire la traccia in Profiler anche se è presente un sovraccarico (NON farlo su una casella di produzione) o esportare la definizione e creare una traccia lato server. Il sovraccarico del Profiler non è un grosso problema per uno sviluppatore o una casella di test dedicati.

Esegui il proc e lascialo completare. A questo punto, puoi anche decidere quale raccogliere il piano di esecuzione effettivo.

Interrompi la traccia e apri il file e dovresti vedere una suddivisione riga per riga del tuo proc, inclusi i tempi per ogni passaggio. Lo trovo più utile del piano per identificare i colli di bottiglia, anche se il piano sarà utile quando si esaminano le sezioni pertinenti da mettere a punto.

HTH


4

È inoltre possibile utilizzare le viste di gestione dinamica sys.dm_exec_procedure_stats e sys.dm_exec_query_stats . Il primo di questi fornisce informazioni sulla procedura nel suo insieme; il secondo può essere utilizzato per suddividere ogni query nella procedura. Di seguito è mostrato un esempio:

USE AdventureWorks;
GO
CREATE PROCEDURE dbo.Test
    @NameLike nvarchar(50)
AS
BEGIN
    SELECT
        ProductCount = COUNT_BIG(*)
    FROM Production.Product AS p
    JOIN Production.TransactionHistory AS th ON
        th.ProductID = p.ProductID
    WHERE
        p.Name LIKE @NameLike;

    SELECT
        pc.Name,
        ProductCount = COUNT_BIG(*)
    FROM Production.Product AS p
    JOIN Production.ProductSubcategory AS ps ON
        ps.ProductSubcategoryID = p.ProductSubcategoryID
    JOIN Production.ProductCategory AS pc ON
        pc.ProductCategoryID = ps.ProductCategoryID
    WHERE
        p.Name LIKE @NameLike
    GROUP BY
        pc.Name
    ORDER BY
        pc.Name;
END;
GO
EXECUTE dbo.Test @NameLike = N'A%';
EXECUTE dbo.Test @NameLike = N'F%';

Statistiche della procedura:

SELECT
    deps.last_execution_time,
    deps.last_worker_time,
    deps.last_physical_reads,
    deps.last_logical_writes,
    deps.last_logical_reads,
    deps.last_elapsed_time
FROM sys.dm_exec_procedure_stats AS deps
WHERE
    deps.database_id = DB_ID()
    AND deps.[object_id] = OBJECT_ID(N'dbo.Test', N'P');

Domande all'interno della procedura:

SELECT
    query.the_text,
    deqs.last_execution_time,
    deqs.last_worker_time,
    deqs.last_physical_reads,
    deqs.last_logical_writes,
    deqs.last_logical_reads,
    deqs.last_clr_time,
    deqs.last_elapsed_time,
    deqs.last_rows    -- note: Only present from 2008 R2 onwards
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.[sql_handle]) AS dest
CROSS APPLY
(
    VALUES 
    (
        SUBSTRING
        (
            dest.[text], 
            deqs.statement_start_offset / 2 + 1,
            (ISNULL(NULLIF(deqs.statement_end_offset, -1), DATALENGTH(dest.[text])) - deqs.statement_start_offset) / 2 + 1
        )
    )
) AS query (the_text)
WHERE
    deqs.[sql_handle] IN
    (
        SELECT
            deps.[sql_handle]
        FROM sys.dm_exec_procedure_stats AS deps
        WHERE
            deps.database_id = DB_ID()
            AND deps.[object_id] = OBJECT_ID(N'dbo.Test', N'P')
    );

Questo è utile e lo userò sicuramente su scatole in cui non riesco a installare SQL Sentry Plan Explorer.
AakashM,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.