Di dunia SQL Server, ada dua tipe orang:mereka yang suka semua objeknya diberi awalan, dan mereka yang tidak. Grup sebelumnya dibagi lagi menjadi dua kategori:mereka yang mengawali prosedur tersimpan dengan sp_
, dan mereka yang memilih awalan lain (seperti usp_
atau proc_
). Rekomendasi lama adalah untuk menghindari sp_
awalan, baik untuk alasan kinerja, dan untuk menghindari ambiguitas atau tabrakan jika Anda memilih nama yang sudah ada di katalog sistem. Tabrakan tentu saja masih menjadi masalah, tetapi dengan asumsi Anda telah memeriksa nama objek Anda, apakah itu masih menjadi masalah kinerja?
Versi TL;DR:YA.
Awalan sp_ tetap tidak boleh. Namun dalam posting ini saya akan menjelaskan mengapa, bagaimana SQL Server 2012 dapat membuat Anda percaya bahwa saran peringatan ini tidak lagi berlaku, dan beberapa efek samping potensial lainnya dari memilih konvensi penamaan ini.
Apa masalahnya dengan sp_?
sp_
awalan tidak berarti apa yang Anda pikirkan:kebanyakan orang berpikir sp
singkatan dari "prosedur tersimpan" padahal sebenarnya itu berarti "khusus." Prosedur tersimpan (serta tabel dan tampilan) disimpan di master dengan sp_
awalan dapat diakses dari database mana pun tanpa referensi yang tepat (dengan asumsi versi lokal tidak ada). Jika prosedur ditandai sebagai objek sistem (menggunakan sp_MS_marksystemobject
(prosedur sistem tidak berdokumen dan tidak didukung yang menetapkan is_ms_shipped
ke 1), maka prosedur di master akan dijalankan dalam konteks database pemanggil. Mari kita lihat contoh sederhana:
CREATE DATABASE sp_test; GO USE sp_test; GO CREATE TABLE dbo.foo(id INT); GO USE master; GO CREATE PROCEDURE dbo.sp_checktable AS SELECT DB_NAME(), name FROM sys.tables WHERE name = N'foo'; GO USE sp_test; GO EXEC dbo.sp_checktable; -- runs but returns 0 results GO EXEC master..sp_MS_marksystemobject N'dbo.sp_checktable'; GO EXEC dbo.sp_checktable; -- runs and returns results GO
Hasil:
(0 row(s) affected) sp_test foo (1 row(s) affected)
Masalah kinerja berasal dari fakta bahwa master mungkin diperiksa untuk prosedur tersimpan yang setara, tergantung pada apakah ada versi lokal dari prosedur tersebut, dan apakah sebenarnya ada objek yang setara di master. Ini dapat menyebabkan overhead metadata tambahan serta SP:CacheMiss
tambahan peristiwa. Pertanyaannya adalah apakah overhead ini nyata.
Jadi mari kita pertimbangkan prosedur yang sangat sederhana dalam database pengujian:
CREATE DATABASE sp_prefix; GO USE sp_prefix; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
Dan prosedur yang setara di master:
USE master; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'master', DB_NAME(); END GO EXEC sp_MS_marksystemobject N'sp_something';
CacheMiss :Fakta atau Fiksi?
Jika kita menjalankan tes cepat dari database pengujian kita, kita melihat bahwa mengeksekusi prosedur tersimpan ini tidak akan pernah benar-benar memanggil versi dari master, terlepas dari apakah kita benar database atau skema-mengkualifikasi prosedur (kesalahpahaman umum) atau jika kita menandai versi master sebagai objek sistem:
USE sp_prefix; GO EXEC sp_prefix.dbo.sp_something; GO EXEC dbo.sp_something; GO EXEC sp_something;
Hasil:
sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix
Mari kita juga menjalankan Jejak CepatSP:CacheMiss
acara:
Kami melihat CacheMiss
kejadian untuk kumpulan ad hoc yang memanggil prosedur tersimpan (karena SQL Server umumnya tidak akan mengganggu cache kumpulan yang terutama terdiri dari panggilan prosedur), tetapi tidak untuk prosedur tersimpan itu sendiri. Baik dengan dan tanpa sp_something
prosedur yang ada di master (dan ketika ada, baik dengan dan tanpa ditandai sebagai objek sistem), panggilan ke sp_something
di database pengguna jangan pernah "secara tidak sengaja" memanggil prosedur di master, dan jangan pernah membuat CacheMiss
peristiwa untuk prosedur.
Ini pada SQL Server 2012. Saya mengulangi tes yang sama di atas pada SQL Server 2008 R2, dan menemukan hasil yang sedikit berbeda:
Jadi pada SQL Server 2008 R2 kita melihat tambahan CacheMiss
peristiwa yang tidak terjadi di SQL Server 2012. Ini terjadi di semua skenario (tidak ada master objek yang setara, objek di master ditandai sebagai objek sistem, dan objek di master tidak ditandai sebagai objek sistem). Saya langsung penasaran apakah acara tambahan ini akan berdampak nyata pada kinerja.
Masalah Kinerja:Fakta atau Fiksi?
Saya membuat prosedur tambahan tanpa sp_
awalan untuk membandingkan kinerja mentah, CacheMiss
samping:
USE sp_prefix; GO CREATE PROCEDURE dbo.proc_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
Jadi satu-satunya perbedaan antara sp_something
dan proc_something
. Saya kemudian membuat prosedur pembungkus untuk mengeksekusinya masing-masing 1000 kali, menggunakan EXEC sp_prefix.dbo.<procname>
, EXEC dbo.<procname>
dan EXEC <procname>
sintaks, dengan prosedur tersimpan setara yang hidup di master dan ditandai sebagai objek sistem, tinggal di master tetapi tidak ditandai sebagai objek sistem, dan tidak hidup di master sama sekali.
USE sp_prefix; GO CREATE PROCEDURE dbo.wrap_sp_3part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC sp_prefix.dbo.sp_something; SET @i += 1; END END GO CREATE PROCEDURE dbo.wrap_sp_2part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC dbo.sp_something; SET @i += 1; END END GO CREATE PROCEDURE dbo.wrap_sp_1part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC sp_something; SET @i += 1; END END GO -- repeat for proc_something
Mengukur durasi runtime setiap prosedur wrapper dengan SQL Sentry Plan Explorer, hasilnya menunjukkan bahwa menggunakan sp_
awalan memiliki dampak signifikan pada durasi rata-rata di hampir semua kasus (dan tentu saja rata-rata):