Masih salah untuk memulai nama prosedur yang disimpan pengguna dengan sp_?

33

Salah satu rekan kerja saya menyebutkan prosedur tersimpan di database SQL Server 2008 R2 kami sp_something. Ketika saya melihat ini, saya langsung berpikir: "Itu SALAH!" dan mulai mencari bookmark saya untuk artikel online ini yang menjelaskan mengapa itu salah, jadi saya bisa memberikan penjelasan kepada rekan kerja saya.

Dalam artikel (oleh Brian Moran ) dijelaskan bahwa memberikan prosedur tersimpan awalan sp_ membuat SQL Server melihat pada master database untuk rencana yang dikompilasi. Karena sp_sproctidak berada di sana, SQL Server akan mengkompilasi ulang prosedur (dan memerlukan kunci kompilasi eksklusif untuk itu, menyebabkan masalah kinerja).

Contoh berikut diberikan dalam artikel untuk menunjukkan perbedaan antara dua prosedur:

USE tempdb;
GO

CREATE PROCEDURE dbo.Select1 AS SELECT 1;
GO

CREATE PROCEDURE dbo.sp_Select1 AS SELECT 1;
GO

EXEC dbo.sp_Select1;
GO

EXEC dbo.Select1;
GO

Anda menjalankan ini, lalu buka Profiler (tambahkan Prosedur Disimpan -> SP:CacheMissacara) dan jalankan prosedur yang tersimpan lagi. Anda seharusnya melihat perbedaan antara dua prosedur tersimpan: prosedur sp_Select1tersimpan akan menghasilkan satu SP:CacheMissperistiwa lebih dari Select1prosedur tersimpan (artikel referensi SQL Server 7.0 dan SQL Server 2000. )

Ketika saya menjalankan contoh di lingkungan SQL Server 2008 R2 saya, saya mendapatkan jumlah SP:CacheMissperistiwa yang sama untuk kedua prosedur (baik di tempdb dan di database pengujian lain).

Jadi saya bertanya-tanya:

  • Bisakah saya melakukan sesuatu yang salah dalam eksekusi contoh saya?
  • Apakah sproc sp_somethingadagium 'jangan beri nama pengguna ' masih valid di versi SQL Server yang lebih baru?
  • Jika demikian, apakah ada contoh yang baik yang menunjukkan validitasnya dalam SQL Server 2008 R2?

Terima kasih banyak atas pemikiran Anda tentang ini!

EDIT

Saya menemukan Membuat Prosedur yang Disimpan (Database Engine) di msdn untuk SQL Server 2008 R2, yang menjawab pertanyaan kedua saya:

Kami menyarankan Anda untuk tidak membuat prosedur tersimpan menggunakan sp_ sebagai awalan. SQL Server menggunakan awalan sp_ untuk menunjuk prosedur yang tersimpan sistem. Nama yang Anda pilih mungkin bertentangan dengan beberapa prosedur sistem di masa depan. [...]

Tidak ada yang disebutkan di sana tentang masalah kinerja yang disebabkan oleh penggunaan sp_awalan. Saya ingin tahu apakah itu masih terjadi atau apakah mereka memperbaikinya setelah SQL Server 2000.

marc_s
sumber
3
Saya memang melihat ini sebelumnya dan menemukan perbedaan kinerja yang dapat diabaikan yang saya meletakkan ke atas sedikit lebih besar dari penyelesaian sp_versi (perlu memeriksa di master dan database pengguna karena memprioritaskan procs sistem di master-> procs di DB pengguna -> bukan sistem procs in master)
Martin Smith
4
Keuntungan apa yang Anda lihat untuk mengawali prosedur tersimpan sp_? Ini sama bermanfaatnya dengan awalan tabel dengan tbl. Mengapa membuat master pencarian sistem terlebih dahulu (bahkan jika itu diabaikan atau tidak ada perbedaan kinerja) untuk memungkinkan Anda menggunakan konvensi penamaan yang tidak berarti ini?
Aaron Bertrand
1
@ AaronBertrand: sejujurnya, saya melihat tidak ada manfaat sama sekali dalam awalan sprocs dengan sp_, hanya kerugian, dan saya tidak akan pernah awalan dengan cara ini sendiri. Tetapi saya ingin semua argumen yang saya dapat meyakinkan rekan kerja saya untuk tidak melakukannya juga.
1
Ya, tbl tidak berguna, tapi saya masih suka menggunakannya. Pasti OCD-ku yang menendang. Sekarang pergilah dari halaman.
SQLRockstar
1
@Josien juga, rekan kerja Anda harus datang dengan argumen untuk membuat skema penamaan yang lebih rumit. Buat mereka menjelaskan mengapa dbo.sp_Author_Renamelebih baik daripada dbo.Author_Rename. Saya tidak dapat memikirkan satu hal pun yang masuk akal.
Aaron Bertrand

Jawaban:

31

Ini cukup mudah untuk menguji diri Anda. Mari kita buat dua prosedur yang sangat sederhana:

CREATE PROCEDURE dbo.sp_mystuff
AS
  SELECT 'x';
GO
CREATE PROCEDURE dbo.mystuff
AS
  SELECT 'x';
GO

Sekarang mari kita membangun pembungkus yang mengeksekusi mereka beberapa kali, dengan dan tanpa awalan skema:

CREATE PROCEDURE dbo.wrapper_sp1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC sp_mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_sp2
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC dbo.sp_mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_2
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC dbo.mystuff;
      SET @i += 1;
    END
END
GO

Hasil:

masukkan deskripsi gambar di sini

Kesimpulan:

  • menggunakan awalan sp_ lebih lambat
  • meninggalkan awalan skema lebih lambat

Pertanyaan yang lebih penting: mengapa Anda ingin menggunakan awalan sp_? Apa yang rekan kerja Anda berharap untuk mendapatkan dari melakukannya? Ini seharusnya bukan tentang Anda harus membuktikan bahwa ini lebih buruk, itu harus tentang mereka membenarkan menambahkan awalan tiga huruf yang sama untuk setiap prosedur tersimpan tunggal dalam sistem. Saya gagal melihat manfaatnya.

Juga saya melakukan beberapa pengujian yang cukup luas dari pola ini di posting blog berikut:

http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix

Aaron Bertrand
sumber
Catatan, hasil ini ada di SQL Server 2012. Tapi Anda bisa melakukan tes yang sama di lingkungan Anda.
Aaron Bertrand
1
"Apa yang diharapkan rekan kerja Anda dari melakukannya" lihat juga Hongaria Notasi . Pada dasarnya, ini adalah hal 90-an untuk sebagian besar. Juga, pada pekerjaan saya yang lalu standarnya adalah untuk mengawali setiap prosedur yang tersimpan dengan sp_sehingga mereka dapat dibedakan dari hal-hal lain dan tidak ada konflik nama ... Saya tidak tahu ada masalah kinerja ini dengan itu.
Earlz
Contoh yang bagus, terima kasih Aaron. Saya masih mengujinya pada 2008 R2 (dan mungkin mengujinya dengan cara yang salah, menyebabkan 'dbo.wrapper_sp1' dan 'dbo.wrapper_sp2' tampaknya jauh lebih cepat daripada dua lainnya sekarang).
12

Kami menyarankan Anda untuk tidak membuat prosedur tersimpan menggunakan sp_ sebagai awalan. SQL Server menggunakan awalan sp_ untuk menunjuk prosedur yang tersimpan sistem. Nama yang Anda pilih mungkin bertentangan dengan beberapa prosedur sistem di masa depan. [...]

Tidak ada yang disebutkan di sana tentang masalah kinerja yang disebabkan oleh penggunaan awalan sp_. Saya ingin tahu apakah itu masih terjadi atau apakah mereka memperbaikinya setelah SQL Server 2000.

Seperti yang ditunjukkan oleh komentar sederhana Martin Smith - ya, jika Anda memiliki prosedur tersimpan dengan sp_awalan - pelaksana kueri SQL Server akan selalu memeriksa dalam masterdatabase terlebih dahulu untuk melihat apakah prosedur yang disimpan (ditandai sebagai prosedur yang disimpan sistem) dengan nama itu ada.

Dan jika ada, prosedur yang disimpan sistem dari masterdatabase selalu menang dan akan dieksekusi bukan milik Anda.

Jadi ya - itu masih berdiri: tidak menggunakan yang sp_awalan.

marc_s
sumber
5
Mudah diuji. CREATE PROC dbo.sp_helptext AS SELECT 1lalu cobaEXEC dbo.sp_helptext
Martin Smith
Terima kasih atas jawaban Anda, tambahan yang sangat berguna pada prevalensi mastersp.
2

Tes yang lebih baik adalah menulis kueri yang memerlukan optimisasi penuh karena kemungkinan itu merupakan cerminan yang lebih baik dari apa yang sedang Anda lakukan. Saya membungkus kueri berikut dalam SP dan mengulangi pengujian Anda dan mendapatkan hasil yang sama.

select * from Person.BusinessEntity b
inner join Person.BusinessEntityAddress ba on b.BusinessEntityID = ba.BusinessEntityID
inner join Person.Address a on ba.AddressID = a.AddressID

Saya mendapatkan jumlah cache miss dan hit yang sama dalam kedua kasus dan dalam kedua kasus paket ditambahkan ke cache. Saya juga menjalankan kedua procs beberapa kali dan tidak ada perbedaan yang konsisten dalam waktu CPU atau waktu yang berlalu yang dilaporkan oleh dm_exec_query_stats.

Kekhawatiran lainnya adalah karena procs "sp_" dapat dieksekusi dari master sehingga Anda bisa mendapatkan salinan proc yang dijalankan menjadi master alih-alih DB yang sedang Anda kerjakan, tetapi tes cepat akan menunjukkan bukan itu masalahnya. Namun, jika proc dikeluarkan dari DB tempat Anda bekerja dan salinannya ada di master maka itu akan dieksekusi yang bisa menjadi masalah jika itu versi lama. Jika ini masalah, saya tidak akan menggunakan "sp_" untuk memberi nama proc.

cfradenburg
sumber
Temuan yang menarik, terima kasih! Saya akan menggunakan contoh Anda dalam kombinasi dengan contoh Aaron untuk menjalankan beberapa tes lagi.
1

Saya percaya masalah ini harus dilakukan ketika Anda tidak menentukan nama objek yang memenuhi syarat. Jadi, "EXEC sp_something" akan memeriksa master terlebih dahulu, tetapi "EXEC dbname.dbo.sp_something" tidak akan pernah pergi ke master terlebih dahulu.

Pelajaran, jika saya ingat, adalah untuk selalu menggunakan nama yang sepenuhnya memenuhi syarat.

SQLRockstar
sumber
5
Jangan berpikir itu membuat perbedaan. EXEC MyDB.dbo.sp_helptext 'sp_helptext'masih menggunakan yang dari masterbahkan jika ada satu di basis data pengguna. AFAIK memeriksa kedua lokasi dan akan menggunakan satu dari masterjika ada dan ditandai sebagai objek sistem.
Martin Smith
1
@ MartinSmith pada 2012 saya tidak bisa memaksa versi master untuk dieksekusi (meskipun tes saya di sana memang menunjukkan ada sesuatu yang terjadi), kecuali saya menjatuhkan salinan lokal (dalam hal ini MyDB.dbo.sp_foomasih dieksekusi versi master). Saya tidak memiliki 2008/2008 R2 sekarang untuk mengkonfirmasi di mana perilaku ini berubah.
Aaron Bertrand
@ AaronBertrand - Ah, menarik saya melakukan pengujian pada 2008 R2.
Martin Smith
Juga perhatikan bahwa jika prosedur lokal tidak ditemukan dan satu ditemukan di master, yang terakhir akan dieksekusi, dan tidak perlu ditandai sebagai objek sistem untuk ini terjadi. Dan setidaknya pada 2012, apakah salinan master ditandai atau tidak sebagai objek sistem, tidak mengubah perilaku - dengan atau tanpa awalan db / skema lokal, salinan lokal selalu dijalankan kecuali tidak ada.
Aaron Bertrand
1
Ups, saya seharusnya mengklarifikasi bahwa komentar saya ditujukan pada jawaban yang disarankan. Komentar SQLRockstar "EXEC dbname.dbo.sp_something tidak akan pernah menjadi master terlebih dahulu." salah.
Greenstone Walker