Bir kullanıcı saklı yordamın adını sp_ ile başlatmak için hala yanlış?


33

İş arkadaşlarımdan biri SQL Server 2008 R2 veritabanında saklı bir prosedür belirledi sp_something. Bunu gördüğümde hemen düşündüm: "Bu YANLIŞ!" ve neden yanlış olduğunu açıklayan bu çevrimiçi makale için yer işaretlerimi aramaya başladım , böylece iş arkadaşıma bir açıklama yapabilirdim.

Makalede ( Brian Moran tarafından ) saklı yordamın bir sp_ öneki verilmesi, SQL Server'ın derlenmiş bir plan için ana veritabanına bakmasını sağladığı açıklanmıştır . Çünkü sp_sprocorada bulunmuyorsa, SQL Server (performans sorunlarına yol ve bunun için özel bir derleme kilidi gerekiyor) prosedürünü yeniden derlemek olacaktır.

İki örnek arasındaki farkı göstermek için makalede aşağıdaki örnek verilmiştir:

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

Bunu çalıştırın, sonra Profiler'ı açın (Saklı Prosedürler -> SP:CacheMissolayı ekleyin ) ve saklı yordamları tekrar çalıştırın. İki saklı yordam arasında bir fark görmeniz gerekir: sp_Select1saklı yordam saklı yordamdan bir SP:CacheMissolay daha oluşturur Select1(makale SQL Server 7.0 ve SQL Server 2000'e başvurur .)

Örneği SQL Server 2008 R2 ortamımda çalıştırdığımda, SP:CacheMissher iki prosedür için de aynı miktarda olay elde ediyorum (hem tempdb'de hem de başka bir test veritabanında).

Bu yüzden merak ediyorum:

  • Örneği yürütürken yanlış bir şey yapabilir miyim?
  • 'Kullanıcı adı yok sproc sp_something' adagium, SQL Server'ın daha yeni sürümlerinde hala geçerli mi?
  • Öyleyse, SQL Server 2008 R2'deki geçerliliğini gösteren iyi bir örnek var mı?

Bu konudaki düşünceleriniz için çok teşekkür ederiz!

DÜZENLE

Bulduğum Saklı Prosedürler (Veritabanı Altyapısı) oluşturma benim ikinci soru cevaplar SQL Server 2008 R2 için msdn üzerinde:

Sp_'yi önek olarak kullanan hiçbir saklı yordam oluşturmamanızı öneririz. SQL Server, sistem saklı prosedürlerini belirlemek için sp_ önekini kullanır. Seçtiğiniz ad gelecekteki bazı sistem prosedürleriyle çakışabilir. [...]

Orada önek kullanılmasından kaynaklanan performans sorunları hakkında hiçbir şey söylenmedi sp_. Bunun hala geçerli olup olmadığını veya SQL Server 2000'den sonra düzelttiklerini bilmek isterim.


3
Daha önce buna baktım ve sp_sürümleri çözme konusunda biraz daha fazla yüke indirdiğim önemsiz bir performans farkı buldum (hem ana hem de kullanıcı veritabanlarını kontrol etmek gerekiyor, çünkü sistem işleminde sistem işlemlerinde master-> işlem yapılmıyor. procs) master)
Martin Smith

4
Saklı yordamın ön ekini almanın ne yararı var? sp_ ? Bu, bir tablonun ön eklenmesi kadar faydalıdır tbl. Neden bu anlamsız adlandırma kuralını kullanmanıza izin vermek için, ilk önce sistem aramasını ana (önemsiz olsa da veya performans farkı olmasa da) yapalım?
Aaron Bertrand

1
@AaronBertrand: dürüst olmak gerekirse, ben hiçbir fayda görmek hiç sp_who, sadece dezavantajları ile SPROCs prefixing içinde, ben bu yolu kendim onları öneki asla. Ancak iş arkadaşlarımın bunu yapmamasına ikna etmek için alabildiğim tüm tartışmaları istiyorum.

1
Evet, tbl işe yaramaz, ama yine de kullanmayı seviyorum. Tekmelemem gereken OKB olmalı. Şimdi çimlerimden defol.
SQLRockstar

1
@Josien ayrıca, çalışma arkadaşlarınızın bir isimlendirme düzenini daha karmaşık hale getirmek için tartışmalarla gelmesi gerekiyor . Neden dbo.sp_Author_Renamedaha iyi olduğunu açıklamalarını sağlayın dbo.Author_Rename. Mantıklı olan tek bir şey düşünemiyorum.
Aaron Bertrand

Yanıtlar:


31

Bu kendinizi sınamak için oldukça kolaydır. İki çok basit prosedür oluşturalım:

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

Şimdi şema öneki olsun olmasın, onları birkaç kez yürüten bir sarmalayıcı oluşturalım:

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

Sonuçlar:

görüntü tanımını buraya girin

Sonuç:

  • sp_ öneki kullanmak daha yavaş
  • şema ön ekini bırakmak daha yavaştır

Daha önemli bir soru: neden olmasın istediğiniz sp_who öneki kullanılır? İş arkadaşlarınız bu şekilde ne kazanmayı umuyor ? Bu, bunun daha kötü olduğunu kanıtlamanızla ilgili olmamalı, sistemdeki her bir saklı yordam için aynı üç harfli ön ekin eklenmesini haklı göstermeli. Yararı göremiyorum.

Ayrıca, aşağıdaki blog gönderisinde bu modelin oldukça kapsamlı testlerini yaptım:

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


Not: Bu sonuçlar SQL Server 2012'dedir. Ancak aynı testleri ortamınızda yapabilirsiniz.
Aaron Bertrand

1
“İş arkadaşlarınız bunu yapmaktan ne kazanmayı bekliyorlar?” Bakınız ayrıca Macar Notasyonu . Temel olarak, çoğu zaman 90'ların bir şey. Ayrıca, benim önceki işimde standart, saklanan her prosedürü sp_diğer şeylerden ayırt edebilmeleri ve isim çakışmaları olmamalarını öneriyordu ... Bu performans probleminin onunla ilgili olduğu hakkında hiçbir fikrim yoktu.
Earlz

Harika bir örnek, teşekkürler Aaron. Hala 2008 R2’de test ediyorum (ve muhtemelen yanlış şekilde test ediyorum, çünkü d dbo.wrapper_sp1 ’ve d dbo.wrapper_sp2’ şu anda diğerlerinden daha hızlı görünüyor).

12

Sp_'yi önek olarak kullanan hiçbir saklı yordam oluşturmamanızı öneririz. SQL Server, sistem saklı prosedürlerini belirlemek için sp_ önekini kullanır. Seçtiğiniz ad gelecekteki bazı sistem prosedürleriyle çakışabilir. [...]

Orada sp_ öneki kullanılmasından kaynaklanan performans sorunları hakkında hiçbir şey söylenmedi. Bunun hala geçerli olup olmadığını veya SQL Server 2000'den sonra düzelttiklerini bilmek isterim.

Bir ile saklı bir yordam varsa evet - Martin Smith'in basit açıklama gösterdiği gibi sp_önek - SQL Server sorgu infaz edecek hep checkmaster bu adla saklı bir yordamın (sistem saklı yordam olarak işaretlenmiş) var olup olmadığını görmek için önce veritabanını .

Ve varsa, masterveritabanındaki bu sistem saklı yordam her zaman geçerlidir ve kendiniz yerine yürütülecektir.

Yani evet - bu hala duruyor: kullanmayansp_ önek.


5
Test etmek basit. CREATE PROC dbo.sp_helptext AS SELECT 1sonra deneyinEXEC dbo.sp_helptext
Martin Smith

Cevabınız için teşekkürler, mastersp's prevalansına çok yararlı bir katkı .

2

Daha iyi bir test, tam optimizasyon gerektiren bir sorgu yazmaktır; çünkü bu, yazdığınız proc'un ne yaptığının daha iyi bir yansımasıdır. Aşağıdaki sorguyu bir SP'ye sardım ve testinizi tekrarladım ve aynı sonuçları aldım.

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

Her iki durumda da aynı sayıda önbellek özledim ve isabet olayları aldım ve her iki durumda da plan önbelleğe eklendi. Her iki işlemi de birkaç kez koştum ve dm_exec_query_stats tarafından bildirilen CPU süresi veya geçen süre arasında tutarlı bir fark yoktu.

Diğer bir endişe de, "sp_" procs'ları ustadan çalıştırılabildiğinden, üzerinde çalıştığınız DB yerine usta olan proc'un bir kopyasını alabilmenizdir, ancak hızlı bir test bunun böyle olmadığını gösterecektir. Ancak, proc çalıştığınız DB'den çıkarılırsa ve master'da bir kopyası varsa, eski bir sürümse sorun olabilecek bir işlem yürütülür. Bu bir endişe ise, proc ismini vermek için "sp_" kullanmam.


İlginç bulgular, teşekkürler! Birkaç test daha yapmak için örneğinizi Aaron'un örneğiyle birlikte kullanacağım.

1

Tam nitelikli nesne adını belirtmediğinizde sorunun yapılması gerektiğine inanıyorum. Böylece, "EXEC sp_something" önce master'ı kontrol eder, ancak "EXEC dbname.dbo.sp_something" asla önce master'a gitmez.

Hatırlarsam, ders her zaman tam adı kullanmaktır.


5
Bunun bir fark yaratacağını düşünme. kullanıcı veritabanında bir tane olsa bile EXEC MyDB.dbo.sp_helptext 'sp_helptext', hala birini kullanıyor master. AFAIK, her iki konumu da kontrol eder ve mastervarsa ve bir sistem nesnesi olarak işaretlenmişse birini kullanır .
Martin Smith

1
@MartinSmith , yerel kopyasını bırakmadığım sürece (ki bu durumda ana sürümü uyguladıysam ), testlerimin yürütülmesini ana versiyona zorlayamadım (oradaki testlerimde bir şeyler olduğunu gösterdi MyDB.dbo.sp_foo). Şu anda bu davranışın nerede değiştiğini doğrulamak için 2008/2008 R2 kullanmıyorum.
Aaron Bertrand

@AaronBertrand - Ah, ilginç 2008 R2 üzerinde testimi yaptım.
Martin Smith

Ayrıca yerel bir prosedür bulunmazsa ve bir usta bulunursa, ikincisinin çalıştırılacağını ve bunun gerçekleşmesi için bir sistem nesnesi olarak işaretlenmesine gerek olmadığını unutmayın . Ve en azından 2012'de, ana kopyanın bir sistem nesnesi olarak işaretlenmiş olup olmadığı, davranışı değiştirmez - yerel db / şema öneki olsun ya da olmasın, yerel kopya, varolmadıkça daima yürütülür.
Aaron Bertrand

1
Hata! Yorumumun önerilen cevaba yönelik olduğunu açıklamalıydım. SQLRockstar'ın yorumu "EXEC dbname.dbo.sp_something asla ilk önce ustalaşmayacak." yanlış.
Greenstone Walker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.