Taksiran versus rencana kueri aktual dengan panggilan fungsi

11

Saya memiliki kueri ini di SQL server, kueri replikasi gabungan:

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

Perkiraan rencana kueri mencakup informasi tentang 3 kueri:

  1. Permintaan di atas
  2. Fungsi panggilan ke fn_MSgeneration_downloadonly
  3. Fungsi panggilan ke fn_MSArticle_has_downloadonly_property

Paket permintaan aktual hanya mencakup informasi ini:

  1. Permintaan di atas

Tidak ada tentang fungsi. Mengapa informasi fungsi hilang dalam rencana aktual?

Saya mencoba opsi ini:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

Yang membuat rencana aktual, tetapi bagian 2 dan 3 hilang sama dengan ketika saya menggunakan opsi rencana kueri aktual di Management Studio.

Jika misalnya saya akan menggunakan Profiler untuk menangkap informasi tentang fungsi panggilan acara apa yang akan saya pilih?


Tidak menemukan jawaban yang secara khusus terkait dengan rencana kueri, tetapi saya membuat profil SP: StmtStarting dan SP: StmtCompleted dan itu menunjukkan panggilan fungsi.

Peter
sumber

Jawaban:

17

Dan tidak ada tentang fungsi. Mengapa informasi fungsi hilang dalam rencana aktual?

Ini dengan desain, untuk alasan kinerja.

Fungsi yang mengandung BEGINdan ENDdalam definisi membuat bingkai T-SQL stack baru untuk setiap baris input. Dengan kata lain, fungsi tubuh dijalankan secara terpisah untuk setiap baris input . Fakta tunggal ini menjelaskan sebagian besar masalah kinerja yang terkait dengan fungsi skalar dan multi-pernyataan T-SQL (perhatikan bahwa fungsi bernilai tabel in-line tidak menggunakan BEGIN...ENDsintaks).

Dalam konteks pertanyaan Anda, ini akan menghasilkan SHOWPLANoutput penuh untuk setiap baris. Output rencana XML cukup bertele-tele dan mahal untuk diproduksi, sehingga menghasilkan output penuh untuk setiap baris akan menjadi ide yang buruk secara umum.

Contoh

Pertimbangkan fungsi skalar T-SQL di bawah ini, dibuat dalam database sampel AdventureWorks , yang mengembalikan nama produk yang diberikan ID-nya:

CREATE FUNCTION dbo.DumbNameLookup
(
    @ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
    RETURN
    (
        SELECT
            p.Name
        FROM Production.Product AS p
        WHERE
            p.ProductID = @ProductID
    );
END;

Rencana pra-eksekusi

Rencana pra-eksekusi (rencana taksiran dalam SSMS) menampilkan informasi paket untuk pernyataan induk dan panggilan fungsi bersarang:

-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;

Output SSMS:

Rencana pra-eksekusi SSMS

XML yang sama dengan yang dilihat di SQL Sentry Plan Explorer menunjukkan sifat panggilan yang lebih jelas:

Rencana pra-eksekusi PE

Output pasca-eksekusi

SSMS menunjukkan detail hanya untuk kueri utama ketika output rencana pasca-eksekusi diminta:

-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;

SSMS pasca-eksekusi

Dampak kinerja dari melakukan hal lain dapat ditampilkan dengan menggunakan Kelas Peristiwa Profil Statistik Statistik Tampilkan XML di SQL Server Profiler, menggunakan kueri yang memanggil fungsi beberapa kali (satu kali per baris input):

SELECT TOP (5)
    p.ProductID,
    dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;

Output profiler:

Lacak keluaran

Ada lima rencana pasca-eksekusi terpisah untuk eksekusi fungsi, dan satu untuk kueri induk. Lima rencana fungsi terlihat seperti ini di panel bawah profiler:

Rencana fungsi

Paket kueri induk adalah:

Rencana induk

Mengeksekusi kueri tanpa TOP (5)klausa menghasilkan rencana eksekusi penuh untuk masing-masing 504 baris dalam tabel Produk. Anda mungkin dapat melihat bagaimana ini dengan cepat keluar dari tangan dengan meja yang lebih besar.

Situasi untuk pemicu dibalik. Ini tidak menunjukkan informasi rencana pra-eksekusi, tetapi menyertakan rencana pasca-eksekusi. Ini mencerminkan sifat dasar pemicu; masing-masing dipecat satu kali untuk semua baris yang terpengaruh, bukan satu kali per baris.

Paul White 9
sumber
@ PaulWhite apakah ada alasan bagus mengapa rencana pemicu tidak ditampilkan saat meminta perkiraan rencana eksekusi? Itu sepertinya fitur hilang yang bermanfaat. Saya mungkin membuat item terhubung untuk itu.
usr
@ usr - Mungkin karena paket cache aktual yang dipilih dapat bervariasi tergantung pada jumlah baris aktual seperti yang dijelaskan di sini? technet.microsoft.com/en-us/library/…
Martin Smith
@ MartinSmith mungkin itu alasannya. Baru-baru ini item yang terhubung untuk rencana pelaksanaan kendala check dan fk ditandai telah selesai jadi saya berharap mereka akan melakukan hal yang sama dengan pemicu.
usr
@ usr - Yang ini di sini ? 3 bulan? Itu harus menjadi catatan balik untuk permintaan fitur baru!
Martin Smith
@ MartinSmith ya, yang itu. Itu "diperbaiki" 1-2 yang lalu. Saya benar-benar berharap saya tidak perlu meminta toko query. Saya berharap untuk mengklik tombol di SSMS. Sebenarnya, saya terkejut melihat perubahan apa pun pada bagian mesin yang tidak tersentuh selama bertahun-tahun. Tapi mungkin tidak ada.
usr