Bisakah saya mendapatkan SSMS untuk menunjukkan kepada saya biaya permintaan aktual di panel rencana eksekusi?

8

Saya memperbaiki masalah kinerja pada prosedur tersimpan multistatement di SQL Server. Saya ingin tahu bagian mana yang harus saya habiskan.

Saya mengerti dari Bagaimana saya membaca Biaya Permintaan, dan apakah selalu berupa persentase? bahwa bahkan ketika SSMS diberitahu untuk menyertakan Rencana Eksekusi Aktual , angka "Biaya kueri (relatif terhadap bets)" masih didasarkan pada perkiraan biaya , yang mungkin jauh dari aktual

Saya mengerti dari Mengukur Kinerja Kueri: "Biaya Permintaan Rencana Eksekusi" vs "Waktu Diambil" bahwa saya dapat mengelilingi permohonan prosedur tersimpan dengan SET STATISTICS TIMEpernyataan, dan kemudian saya akan mendapatkan daftar seperti ini di Messagespanel:

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.

dengan satu pesan keluaran untuk setiap pernyataan.

Saya dapat 'dengan mudah' (walaupun tidak dengan mudah) mengaitkan output statistik waktu dengan rencana pelaksanaan pernyataan demi pernyataan di panel rencana Eksekusi, dengan menghitungnya: SQL Server Execution TimesOutput pesan keempat sesuai dengan Query 4di panel rencana Eksekusi, dan seterusnya.

Tetapi apakah ada cara yang lebih baik?

AakashM
sumber

Jawaban:

8

Saya tidak tahu cara untuk melakukan ini dalam rencana dari Management Studio, tetapi ini adalah salah satu dari banyak hal yang akan dilakukan SentryOne Plan Explorer gratis untuk Anda ketika Anda membuat rencana aktual dari dalam alat - termasuk semua metrik runtime per pernyataan.

Aaron Bertrand
sumber
Wow, ini terlihat megah. Asal saya yakin saja, kolom hasil Durationdan CPUlebih aktual daripada perkiraan, ya?
AakashM
@ AashashM ya, itu adalah aktual.
Aaron Bertrand
5

Salah satu cara yang baik untuk melakukan ini adalah dengan Profiler. Atur "repro" dari proc Anda pada dev atau kotak tes, yaitu contoh panggilan ke proc dengan parameter. Kemudian menggunakan Profiler, buat jejak menggunakan templat TSQL_SPs, atau dari templat kosong, tambahkan SP: acara StmtCompleted. Tambahkan kolom Durasi, Baca, Tulis, dan CPU jika belum tersedia. Tambahkan filter ke jejak pada SPID Anda (yang harus Anda ketahui dari Management Studio). Anda juga dapat menambahkan filter ke Durasi (mis. Lebih besar dari 1000 = lebih dari 1 detik).

Anda dapat menjalankan penelusuran di Profiler meskipun ada overhead (JANGAN lakukan ini di kotak produksi) atau ekspor definisi dan buat jejak sisi server. Overhead Profiler bukan masalah besar pada dev atau kotak uji khusus.

Jalankan proc dan biarkan selesai. Anda juga dapat mengumpulkan rencana Eksekusi Aktual pada saat ini.

Hentikan jejak Anda dan buka file tersebut, dan Anda akan melihat perincian baris demi baris dari proc Anda, termasuk pengaturan waktu untuk setiap langkah. Saya menemukan ini lebih berguna daripada rencana untuk mengidentifikasi kemacetan meskipun rencana akan berguna ketika melihat bagian yang relevan untuk diperbaiki.

HTH

wBob
sumber
4

Anda juga bisa menggunakan sys.dm_exec_procedure_stats dan sys.dm_exec_query_stats pandangan manajemen dinamis. Yang pertama memberikan informasi tentang prosedur secara keseluruhan; yang kedua dapat digunakan untuk memecahkan setiap permintaan dalam prosedur. Contohnya ditunjukkan di bawah ini:

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%';

Statistik prosedur:

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

Pertanyaan dalam prosedur:

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')
    );
Paul White 9
sumber
Ini berguna dan saya pasti akan menggunakan ini pada kotak di mana saya tidak dapat menginstal SQL Sentry Plan Explorer.
AakashM