Seberapa buruk Kompilasi SQL berdampak pada kinerja SQL Server?

20

Saya membuat profil contoh SQL Server 2005 dan saya, melalui SQLServer:SQL Statistics - SQL Compilations/secmetrik PerfMon , saya melihat bahwa rata-rata sekitar 170 atau lebih.

Saya mengeluarkan SQL Profiler dan mencari SP: Compile atau SQL: Compile events. Ternyata mereka tidak ada. Saya menemukan Stored Procedure/SP:Recompiledan TSQL/SQL:StmtRecompileacara. Jumlah data yang saya lihat di Profiler menunjukkan bahwa ini adalah peristiwa yang salah untuk dilihat, meskipun saya tidak yakin.

Jadi pertanyaan saya. Jawaban untuk semua ini akan sangat bagus.

  1. Bagaimana saya bisa melihat apa sebenarnya yang dikompilasi di SQL Server?
  2. Apakah saya memilih metrik yang salah untuk dilihat? Baik di Perfmon atau SQL Profiler?
  3. Berkenaan dengan Stored Procedure/SP:Recompiledan TSQL/SQL:StmtRecompileacara di SQL Profiler ... mereka tidak termasuk metrik Durasi. Bagaimana saya bisa mengukur dampak dari peristiwa ini ke sistem jika mereka tidak memberikan cara untuk melihat dampak waktu ke sistem.
AngryHacker
sumber

Jawaban:

33

Kompilasi SQL / detik adalah metrik yang baik, tetapi hanya jika digabungkan dengan Permintaan Batch / detik . Dengan sendirinya, kompilasi per detik tidak terlalu banyak memberi tahu Anda.

Anda melihat 170. Jika jumlah batch per detik hanya 200 (sedikit berlebihan untuk efeknya) maka ya, Anda harus turun ke bagian bawah penyebabnya (kemungkinan besar permintaan yang terlalu sering digunakan untuk permintaan ad hoc dan paket sekali pakai). Tetapi jika batch req Anda per detik berukuran sekitar 5000, maka 170 kompilasi per detik sama sekali tidak buruk. Ini adalah aturan umum bahwa Kompilasi / detik harus 10% atau kurang dari total Permintaan Batch / detik .

Jika Anda benar-benar ingin menelusuri apa yang sedang di-cache, jalankan kueri berikut yang menggunakan DMV yang sesuai:

select
    db_name(st.dbid) as database_name,
    cp.bucketid,
    cp.usecounts,
    cp.size_in_bytes,
    cp.objtype,
    st.text
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) st

Untuk mendapatkan semua paket sekali pakai (hitungan):

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
)
select count(*)
from PlanCacheCte
where usecounts = 1

Untuk mendapatkan rasio jumlah rencana penghitungan sekali pakai yang Anda bandingkan dengan semua paket dalam tembolok:

declare @single_use_counts int, @multi_use_counts int

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @single_use_counts = count(*)
from PlanCacheCte
where usecounts = 1

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @multi_use_counts = count(*)
from PlanCacheCte
where usecounts > 1

select
    @single_use_counts as single_use_counts,
    @multi_use_counts as multi_use_counts,
    @single_use_counts * 1.0 / (@single_use_counts + @multi_use_counts) * 100
        as percent_single_use_counts

Adapun durasi yang ditangkap melalui Jejak SQL Server, itu tidak tersedia untuk acara Kompilasi. Tidak terlalu signifikan untuk melihat durasi atau rasa sakit yang disebabkan oleh kompilasi rencana, karena tidak banyak yang dapat Anda lakukan untuk situasi kasus per kasus. Solusinya adalah dengan mencoba membatasi kompilasi dan rekompilasi melalui rencana penggunaan ulang (pertanyaan parameter, prosedur tersimpan, dll.).

Thomas Stringer
sumber
9

Ada tiga penghitung yang relevan yang harus direkam menggunakan PerfMon (atau solusi pihak ketiga lainnya). Poin kuncinya adalah mencatat entah bagaimana statistik ini.

  • Statistik SQL \ Permintaan Batch / dtk
  • Statistik SQL \ Kompilasi SQL / dtk
  • Statistik SQL \ SQL Kompilasi Ulang / dtk

Seperti yang disebutkan oleh Thomas Stringer , ada baiknya mengawasi rasio kompilasi / permintaan batch. Jelas, lebih rendah lebih baik, tetapi hanya ada pedoman untuk apa yang "baik", dan hanya Anda yang dapat memutuskan apa yang dapat diterima. Jumlah absolut perolehan perf yang akan Anda lihat dengan mengurangi jumlah kompilasi tergantung pada banyak faktor.

Saya juga suka melihat rasio kompilasi / kompilasi , untuk mengetahui jumlah penggunaan kembali rencana kueri. Sekali lagi, lebih rendah lebih baik. Namun, dalam kasus ini, Anda ingin kompilasi ulang terjadi di sistem saat statistik berubah (jika DB hanya baca dan Anda mengkompilasi ulang ... ada yang salah). Sama seperti yang saya katakan sebelumnya, hanya ada pedoman untuk apa yang "baik."

Yang benar-benar ingin Anda lakukan adalah tren angka-angka ini dari waktu ke waktu, jadi jika Anda melihat lonjakan besar di salah satu rasio, sesuatu dikerahkan yang tidak menggunakan rencana kueri dengan benar (idealnya, ini tertangkap selama pengujian) - gunakan Shark's analisis permintaan untuk menemukan penyebabnya. Selain itu, berikut adalah satu untuk menemukan pertanyaan yang sering dikompilasi:

SELECT TOP 50
    qs.plan_generation_num,
    qs.execution_count,
    qs.statement_start_offset,
    qs.statement_end_offset,
    st.text
    FROM sys.dm_exec_query_stats qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
    WHERE qs.plan_generation_num > 1
    ORDER BY qs.plan_generation_num DESC

Jika Anda juga merekam statistik untuk penggunaan CPU, semua statistik dapat dikorelasikan bersama untuk mengetahui seberapa sakitnya, dan seberapa banyak perbaikan Anda membantu. Dalam praktiknya, saya telah menemukan bahwa bahkan hanya satu strategi rencana kueri buruk pada sproc inti dapat membuat server bertekuk lutut; jelas YMMV.

Jon Seigel
sumber