Sementara saya menghormati pengirim, saya dengan rendah hati tidak setuju dengan jawaban yang diberikan dan bukan karena "alasan agama". Dengan kata lain, saya percaya tidak ada fasilitas yang disediakan Microsoft yang mengurangi kebutuhan akan panduan untuk menggunakan prosedur tersimpan.
Setiap panduan yang diberikan kepada pengembang yang mendukung penggunaan kueri teks SQL mentah harus diisi dengan banyak peringatan, sehingga saya pikir saran yang paling bijaksana adalah mendorong penggunaan Prosedur yang Disimpan dan, mencegah tim pengembang Anda untuk terlibat dalam praktik. menanamkan pernyataan SQL dalam kode, atau mengirimkan permintaan SQL mentah, berbasis teks biasa, di luar SQL SPROCs (prosedur tersimpan).
Saya pikir jawaban sederhana untuk pertanyaan mengapa menggunakan SPROC adalah sebagai submitter yang diperkirakan: SPROC diuraikan, dioptimalkan, dan dikompilasi. Dengan demikian, rencana kueri / eksekusi mereka di-cache karena Anda telah menyimpan representasi statis dari sebuah query dan Anda, biasanya, akan memvariasikannya hanya dengan parameter, yang tidak benar dalam kasus pernyataan SQL yang disalin / ditempelkan yang kemungkinan berubah dari halaman-ke-halaman-dan komponen / tingkat, dan sering divariasikan sejauh tabel yang berbeda, bahkan nama database, dapat ditentukan dari panggilan ke panggilan. Mengizinkan jenis dinamis ad hoc iniPengiriman SQL, sangat mengurangi kemungkinan Mesin DB untuk menggunakan kembali rencana permintaan untuk pernyataan ad hoc Anda, menurut beberapa aturan yang sangat ketat. Di sini, saya membuat perbedaan antara permintaan ad hoc dinamis (sesuai dengan pertanyaan yang diajukan) versus penggunaan Sistem SPROC sp_executesql yang efisien.
Lebih khusus lagi, ada komponen berikut:
- Paket permintaan serial dan paralel yang tidak menampung konteks pengguna dan memungkinkan untuk digunakan kembali oleh mesin DB.
- Konteks eksekusi yang memungkinkan penggunaan kembali rencana kueri oleh pengguna baru dengan parameter data berbeda.
- Cache prosedur yang diminta oleh mesin DB untuk menciptakan efisiensi yang kami cari.
Ketika pernyataan SQL dikeluarkan dari halaman web, disebut "pernyataan ad hoc", mesin mencari rencana eksekusi yang ada untuk menangani permintaan tersebut. Karena ini adalah teks yang dikirimkan dari pengguna, itu akan dicerna, diuraikan, dikompilasi, dan dieksekusi, jika valid. Saat ini ia akan menerima biaya permintaan nol. Biaya permintaan digunakan ketika mesin DB menggunakan algoritme untuk menentukan rencana eksekusi mana yang akan diusir dari cache.
Kueri ad hoc menerima nilai biaya kueri asli nol, secara default. Setelah eksekusi selanjutnya dari teks kueri ad hoc yang sama persis, oleh proses pengguna lain (atau yang sama), biaya permintaan saat ini diatur ulang ke biaya kompilasi asli. Karena biaya kompilasi permintaan ad hoc kami adalah nol, ini bukan pertanda baik untuk kemungkinan penggunaan kembali. Jelas, nol adalah bilangan bulat yang paling tidak dihargai, tetapi mengapa itu harus digusur?
Ketika tekanan memori muncul, dan mereka akan melakukannya jika Anda memiliki situs yang sering digunakan, mesin DB menggunakan algoritma pembersihan untuk menentukan bagaimana ia dapat memperoleh kembali memori yang menggunakan cache Prosedur. Ia menggunakan biaya permintaan saat ini untuk memutuskan rencana mana yang akan digusur. Seperti yang Anda duga, paket dengan biaya nol adalah yang pertama diusir dari cache karena nol pada dasarnya berarti "tidak ada pengguna saat ini, atau referensi untuk, paket ini".
- Catatan: Paket eksekusi ad hoc - Biaya saat ini dinaikkan oleh setiap proses pengguna, oleh biaya kompilasi asli paket. Namun, tidak ada biaya maksimum paket yang dapat melebihi biaya kompilasi aslinya ... dalam kasus permintaan ad hoc ... nol. Jadi, itu akan "ditingkatkan" dengan nilai itu ... nol - yang pada dasarnya berarti akan tetap menjadi rencana biaya terendah.
Oleh karena itu, sangat mungkin bahwa rencana seperti itu akan digusur terlebih dahulu ketika tekanan ingatan muncul.
Jadi, jika Anda memiliki server build-out dengan banyak memori "di luar kebutuhan Anda", Anda mungkin tidak mengalami masalah ini sesering server sibuk yang hanya memiliki "cukup" memori untuk menangani beban kerjanya. (Maaf, kapasitas dan pemanfaatan memori server agak subyektif / relatif, meskipun algoritme tidak.)
Sekarang, jika saya secara faktual salah tentang satu atau lebih poin, saya tentu terbuka untuk dikoreksi.
Terakhir, penulis menulis:
"Sekarang kami memiliki optimasi tingkat pernyataan, sehingga kueri yang diparameterisasi dengan benar dari aplikasi dapat memanfaatkan rencana eksekusi yang sama dengan kueri yang tertanam dalam prosedur tersimpan."
Saya yakin penulis mengacu pada opsi "optimalkan untuk beban kerja ad hoc".
Jika demikian, opsi ini memungkinkan untuk proses dua langkah yang menghindari segera mengirim paket permintaan penuh ke cache Prosedur. Itu hanya mengirim potongan permintaan yang lebih kecil di sana. Jika panggilan kueri yang tepat dikirim kembali ke server saat rintisan kueri masih dalam cache Prosedur, rencana eksekusi kueri lengkap disimpan ke cache Prosedur, pada saat itu. Ini menghemat memori, yang selama insiden tekanan memori, mungkin memungkinkan algoritma penggusuran untuk mengusir rintisan Anda lebih jarang daripada rencana permintaan yang lebih besar yang cache. Sekali lagi, ini tergantung pada memori dan pemanfaatan server Anda.
Namun, Anda harus mengaktifkan opsi ini, karena tidak aktif secara default.
Terakhir, saya ingin menekankan bahwa, seringkali, alasan utama pengembang menanamkan SQL di halaman, komponen, dan tempat-tempat lain, adalah karena mereka ingin menjadi fleksibel dan mengirimkan query SQL dinamis ke mesin database. Oleh karena itu, dalam Kasus Penggunaan dunia nyata, mengirimkan teks yang sama, panggilan-panggilan, tidak mungkin terjadi seperti halnya caching / efisiensi yang kami cari, ketika mengirimkan permintaan ad hoc ke SQL Server.
Untuk informasi tambahan, silakan lihat:
https://technet.microsoft.com/en-us/library/ms181055(v=sql.105).aspx
http://sqlmag.com/database-performance-tuning/don-t-fear-dynamic-sql
Terbaik,
Henry