Memahami statistik, rencana eksekusi, dan 'masalah utama yang meningkat'

11

Saya mencoba untuk lebih memahami (secara konseptual) hubungan antara statistik, rencana eksekusi, eksekusi prosedur tersimpan.

Apakah saya benar mengatakan bahwa statistik hanya digunakan ketika membuat rencana eksekusi untuk prosedur tersimpan, dan statistik tersebut tidak digunakan dalam konteks eksekusi aktual? Dengan kata lain, jika ini benar, setelah rencana dibuat (dan dengan asumsi itu digunakan kembali dengan benar), seberapa penting statistik "terkini"?

Saya sangat termotivasi oleh artikel yang saya baca ( Statistik, estimasi baris dan kolom tanggal naik ) yang menggambarkan skenario yang sangat mirip dengan yang saya hadapi setiap hari dengan beberapa basis data klien kami.

Kami memiliki kolom tanggal / waktu naik di salah satu tabel terbesar kami yang kami kueri secara teratur menggunakan prosedur tersimpan yang spesifik.

Bagaimana Anda mencegah rencana eksekusi dari basi ketika Anda memiliki seratus ribu baris yang ditambahkan sehari?

Jika kita sering memperbarui statistik untuk mengatasi masalah ini, apakah masuk akal untuk menggunakan petunjuk OPSI (DAPATKAN) pada kueri prosedur tersimpan ini?

Setiap saran atau rekomendasi akan dihargai.

Pembaruan : Saya menggunakan SQL Server 2012 (SP1).

John Russell
sumber

Jawaban:

5

Apakah saya benar mengatakan bahwa statistik hanya digunakan ketika membuat rencana eksekusi untuk prosedur tersimpan, dan statistik tersebut tidak digunakan dalam konteks eksekusi aktual?

Tidak, yang terjadi adalah bahwa rencana eksekusi untuk prosedur yang tersimpan di-cache. Dengan asumsi ada cukup memori yang tersedia untuk terus memegang rencana, itu tidak akan berubah kecuali salah satu dari yang berikut terjadi (dari Caching dan Penggunaan Kembali Rencana Eksekusi dalam dokumentasi SQL Server, penekanan ditambahkan):

  • Perubahan yang dilakukan pada tabel atau tampilan yang dirujuk oleh kueri (ALTER TABLE dan ALTER VIEW).
  • Perubahan dibuat untuk satu prosedur, yang akan menghapus semua paket untuk prosedur itu dari cache (ALTER PROCEDURE).
  • Perubahan pada indeks apa pun yang digunakan oleh rencana eksekusi.
  • Pembaruan pada statistik yang digunakan oleh rencana eksekusi, dihasilkan baik secara eksplisit dari pernyataan, seperti STATISTIK PEMBARUAN, atau dihasilkan secara otomatis.
  • Menjatuhkan indeks yang digunakan oleh rencana eksekusi.
  • Panggilan eksplisit ke sp_recompile.
  • Sejumlah besar perubahan pada kunci (dihasilkan oleh pernyataan INSERT atau DELETE dari pengguna lain yang memodifikasi tabel yang dirujuk oleh kueri).
  • Untuk tabel dengan pemicu, jika jumlah baris dalam tabel yang dimasukkan atau dihapus tumbuh secara signifikan.
  • Menjalankan prosedur tersimpan menggunakan opsi WITH RECOMPILE.

Jadi, jika statistik diperbarui, rencana yang di-cache akan secara otomatis memasukkan statistik baru ke dalam akun dan dikompilasi ulang.

Bagaimana Anda mencegah rencana eksekusi dari basi ketika Anda memiliki seratus ribu baris yang ditambahkan sehari?

Salah satu caranya adalah jika ada banyak pembaruan pada tabel, seperti yang disebutkan di atas. Beberapa ratus ribu baris yang diubah dapat memenuhi kondisi ini. Tetapi jika Anda ingin memastikan atau memiliki kontrol lebih rinci: dengan memperbarui statistik Anda. Anda dapat mengizinkan SQL Server untuk membuat dan mengelola statistik secara otomatis, atau melakukannya sendiri secara manual. Anda dapat menemukan lebih banyak info tentang metode mana pun di Pembaruan Otomatis SQL Server dan Opsi Statistik Buat Otomatis . Ketika / jika Anda melakukan pembangunan kembali indeks mingguan, ini juga akan memicu rencana untuk diperbarui juga. Lakukan beberapa pengujian untuk melihat apa yang paling bermanfaat bagi Anda, karena memperbarui statistik terlalu sering mungkin tidak menghasilkan hasil kinerja nyata.

Jika kita sering memperbarui statistik untuk mengatasi masalah ini, apakah masuk akal untuk menggunakan petunjuk OPSI (DAPATKAN) pada kueri prosedur tersimpan ini?

Anda tidak perlu menggunakan RECOMPILE, karena berdasarkan kutipan di atas Anda dapat melihat bahwa rencana eksekusi diperbarui dengan tepat setiap kali statistik baru tersedia. Anda mungkin baik-baik saja dengan pembaruan statistik akhir hari (jika Anda benar-benar peduli) tetapi saya tidak berpikir itu secara eksplisit merupakan kebutuhan berdasarkan apa yang telah Anda katakan sejauh ini. Namun, sekali lagi, saya akan mengujinya untuk melihat dampak apa yang mungkin terjadi pada kinerja prosedur tersimpan Anda dan merencanakannya.

LowlyDBA
sumber
RECOMPILEtidak akan menyebabkan pembaruan statistik.
Martin Smith
@MartinSmith Benar! Saya akan mengedit untuk membuatnya lebih jelas.
LowlyDBA
@LowlyDBA dapatkah Anda merujuk ke topik berikut? dba.stackexchange.com/questions/207475/…
lukaszwinski
6

Apakah saya benar mengatakan bahwa statistik hanya digunakan ketika membuat rencana eksekusi

Tidak, statistik yang kedaluwarsa dapat menyebabkan rekompilasi terkait optimalitas dari pernyataan yang terpengaruh.

Kami memiliki kolom tanggal / waktu yang naik di salah satu tabel terbesar kami yang kami kueri secara teratur

Rencana pelaksanaan yang tidak optimal yang disebabkan oleh nilai predikat berada di luar (khususnya di atas) kisaran nilai yang disimpan dalam histogram statistik yang sesuai dikenal sebagai Masalah Kunci Meningkat . Membangun kembali statistik adalah salah satu solusi yang mungkin, tetapi ini bisa menjadi sumber daya yang cukup intensif. Alternatif termasuk:

  • Lacak bendera 2389 dan 2390 . Ini mensyaratkan bahwa indeks ada dengan kolom yang bermasalah sebagai kunci utama. Ini tidak bekerja dengan tabel dipartisi, dan hanya efektif di SQL Server 2014 jika estimator kardinalitas asli digunakan. Bendera jejak 4139 juga mungkin diperlukan jika objek statistik dicap stasioner.

  • Tingkatkan ke SQL Server 2014. Penaksir kardinalitas baru termasuk logika untuk memperkirakan di luar histogram menggunakan informasi kepadatan rata-rata. Ini bisa kurang akurat daripada bendera jejak 2389/2390 dalam beberapa keadaan penting.

  • Aktifkan pembaruan statistik otomatis yang lebih sering untuk tabel besar dengan bendera jejak 2371 . Dengan tanda jejak ini, alih-alih memperbarui setelah 20% + 500 perubahan, hanya SQRT(1000 * Table rows)modifikasi yang diperlukan. Ini bukan solusi yang lengkap seperti yang disebutkan sebelumnya, karena pembaruan mungkin masih belum cukup sering dipicu.

Jika sumber masalah Anda bukanlah kompilasi paket yang terlalu sering berdasarkan nilai predikat di luar histogram, tetapi lebih banyak tentang efek sesekali menyimpan caching rencana buruk seperti itu sebagai akibat dari mengendus parameter, Anda juga dapat mempertimbangkan:

  • Menonaktifkan parameter sniffing menggunakan jejak jejak 4136
  • Menggunakan OPTIMIZE FOR (@parameter = value)untuk menyusun rencana untuk nilai representatif yang diketahui
  • Menggunakan OPTIMIZE FOR (@parameter UNKNOWN)untuk mengoptimalkan menggunakan distribusi rata-rata
  • Menggunakan OPTIMIZE FOR UNKNOWN(sama dengan 4136, tetapi per-kueri)
  • Menggunakan OPTION (RECOMPILE)untuk mengkompilasi setiap waktu, mengendus nilai tertentu. Jika sebagian besar nilai runtime berada dalam histogram, ini mungkin efektif.

Untuk informasi lebih lanjut tentang sniffing parameter, embedding, dan opsi kompilasi ulang, lihat artikel saya di SQLperformance.com.

Paul White 9
sumber