Database
 sql >> डेटाबेस >  >> RDS >> Database

क्या sp_ उपसर्ग अभी भी नहीं-नहीं है?

SQL सर्वर की दुनिया में, दो प्रकार के लोग होते हैं:वे जो अपनी सभी वस्तुओं को उपसर्ग करना पसंद करते हैं, और जो नहीं करते हैं। पूर्व समूह को आगे दो श्रेणियों में विभाजित किया गया है:वे जो संग्रहीत कार्यविधियों को sp_ . के साथ उपसर्ग करते हैं , और जो अन्य उपसर्ग चुनते हैं (जैसे usp_ या proc_ ) sp_ . से बचने के लिए लंबे समय से अनुशंसा की जाती रही है उपसर्ग, दोनों प्रदर्शन कारणों से, और अस्पष्टता या टकराव से बचने के लिए यदि आप ऐसा नाम चुनते हैं जो सिस्टम कैटलॉग में पहले से मौजूद है। टकराव निश्चित रूप से अभी भी एक मुद्दा है, लेकिन यह मानते हुए कि आपने अपने ऑब्जेक्ट नाम की जांच की है, क्या यह अभी भी एक प्रदर्शन समस्या है?

TL;DR संस्करण:हाँ।

sp_ उपसर्ग अभी भी नहीं-नहीं है। लेकिन इस पोस्ट में मैं समझाऊंगा कि क्यों, SQL सर्वर 2012 आपको यह विश्वास दिलाने के लिए कैसे प्रेरित कर सकता है कि यह चेतावनी सलाह अब लागू नहीं होती है, और इस नामकरण सम्मेलन को चुनने के कुछ अन्य संभावित दुष्प्रभाव।

sp_ में क्या समस्या है?

sp_ उपसर्ग का मतलब यह नहीं है कि आपको क्या लगता है कि यह क्या करता है:ज्यादातर लोग सोचते हैं sp "संग्रहीत प्रक्रिया" के लिए खड़ा है जब वास्तव में इसका अर्थ "विशेष" है। संग्रहीत कार्यविधियाँ (साथ ही तालिकाएँ और दृश्य) एक sp_ . के साथ मास्टर में संग्रहीत हैं उपसर्ग किसी भी डेटाबेस से उचित संदर्भ के बिना पहुंच योग्य हैं (यह मानते हुए कि स्थानीय संस्करण मौजूद नहीं है)। यदि प्रक्रिया को सिस्टम ऑब्जेक्ट के रूप में चिह्नित किया गया है (sp_MS_marksystemobject . का उपयोग करके) (एक गैर-दस्तावेजी और असमर्थित सिस्टम प्रक्रिया जो is_ms_shipped . सेट करती है से 1), तो मास्टर में प्रक्रिया कॉलिंग डेटाबेस के संदर्भ में निष्पादित होगी। आइए एक सरल उदाहरण देखें:

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

परिणाम:

(0 row(s) affected)

sp_test    foo

(1 row(s) affected)

प्रदर्शन समस्या इस तथ्य से आती है कि मास्टर को समकक्ष संग्रहीत प्रक्रिया के लिए जांचा जा सकता है, इस पर निर्भर करता है कि प्रक्रिया का स्थानीय संस्करण है या नहीं, और वास्तव में मास्टर में समकक्ष वस्तु है या नहीं। इससे अतिरिक्त मेटाडेटा ओवरहेड के साथ-साथ एक अतिरिक्त SP:CacheMiss . हो सकता है प्रतिस्पर्धा। सवाल यह है कि क्या यह ओवरहेड मूर्त है।

तो आइए एक परीक्षण डेटाबेस में एक बहुत ही सरल प्रक्रिया पर विचार करें:

CREATE DATABASE sp_prefix;
GO
USE sp_prefix;
GO
CREATE PROCEDURE dbo.sp_something
AS
BEGIN
  SELECT 'sp_prefix', DB_NAME();
END
GO

और मास्टर में समकक्ष प्रक्रियाएं:

USE master;
GO
CREATE PROCEDURE dbo.sp_something
AS
BEGIN
  SELECT 'master', DB_NAME();
END
GO
EXEC sp_MS_marksystemobject N'sp_something';

CacheMiss :तथ्य या कल्पना?

यदि हम अपने परीक्षण डेटाबेस से एक त्वरित परीक्षण चलाते हैं, तो हम देखते हैं कि इन संग्रहीत प्रक्रियाओं को निष्पादित करने से वास्तव में कभी भी मास्टर से संस्करणों का आह्वान नहीं होगा, भले ही हम ठीक से डेटाबेस- या स्कीमा-योग्यता प्रक्रिया (एक सामान्य गलत धारणा) या यदि हम चिह्नित करते हैं सिस्टम ऑब्जेक्ट के रूप में मास्टर संस्करण:

USE sp_prefix;
GO
EXEC sp_prefix.dbo.sp_something;
GO
EXEC dbo.sp_something;
GO
EXEC sp_something;

परिणाम:

sp_prefix    sp_prefix
sp_prefix    sp_prefix
sp_prefix    sp_prefix

आइए एक क्विक ट्रेस भी चलाएं® SQL संतरी का उपयोग करके यह देखने के लिए कि क्या कोई SP:CacheMiss है इवेंट:

हम देखते हैं CacheMiss तदर्थ बैच के लिए ईवेंट जो संग्रहीत कार्यविधि को कॉल करते हैं (चूंकि SQL सर्वर आमतौर पर उस बैच को कैशिंग करने में परेशानी नहीं करेगा जिसमें मुख्य रूप से प्रक्रिया कॉल शामिल हैं), लेकिन संग्रहीत कार्यविधि के लिए नहीं। sp_something . के साथ और बिना दोनों मास्टर में मौजूद प्रक्रिया (और जब यह मौजूद है, दोनों के साथ और इसके बिना सिस्टम ऑब्जेक्ट के रूप में चिह्नित किया जा रहा है), sp_something पर कॉल करता है उपयोगकर्ता डेटाबेस में कभी भी "गलती से" प्रक्रिया को मास्टर में कॉल न करें, और कभी भी कोई CacheMiss उत्पन्न न करें प्रक्रिया के लिए घटनाएँ।

यह SQL Server 2012 पर था। मैंने उपरोक्त समान परीक्षण SQL Server 2008 R2 पर दोहराए, और थोड़े भिन्न परिणाम पाए:

तो SQL Server 2008 R2 पर हम एक अतिरिक्त CacheMiss . देखते हैं घटना जो SQL सर्वर 2012 में नहीं होती है। यह सभी परिदृश्यों में होता है (कोई समकक्ष ऑब्जेक्ट मास्टर नहीं, मास्टर में एक ऑब्जेक्ट को सिस्टम ऑब्जेक्ट के रूप में चिह्नित किया जाता है, और मास्टर में एक ऑब्जेक्ट को सिस्टम ऑब्जेक्ट के रूप में चिह्नित नहीं किया जाता है)। तुरंत मैं उत्सुक था कि क्या इस अतिरिक्त घटना का प्रदर्शन पर कोई उल्लेखनीय प्रभाव पड़ेगा।

प्रदर्शन समस्या:तथ्य या कल्पना?

मैंने sp_ . के बिना एक अतिरिक्त प्रक्रिया बनाई कच्चे प्रदर्शन की तुलना करने के लिए उपसर्ग, CacheMiss एक तरफ:

USE sp_prefix;
GO
CREATE PROCEDURE dbo.proc_something
AS
BEGIN
  SELECT 'sp_prefix', DB_NAME();
END
GO

तो sp_something . के बीच एकमात्र अंतर और proc_something . फिर मैंने EXEC sp_prefix.dbo.<procname> का उपयोग करके, उन्हें 1000 बार निष्पादित करने के लिए रैपर प्रक्रियाएं बनाईं। , EXEC dbo.<procname> और EXEC <procname> सिंटैक्स, मास्टर में रहने वाले समकक्ष संग्रहीत प्रक्रियाओं के साथ और सिस्टम ऑब्जेक्ट के रूप में चिह्नित, मास्टर में रहना लेकिन सिस्टम ऑब्जेक्ट के रूप में चिह्नित नहीं, और मास्टर में बिल्कुल नहीं रहना।

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

SQL संतरी योजना एक्सप्लोरर के साथ प्रत्येक रैपर प्रक्रिया की रनटाइम अवधि को मापने के परिणाम दिखाते हैं कि sp_ का उपयोग करना उपसर्ग का लगभग सभी मामलों में औसत अवधि पर महत्वपूर्ण प्रभाव पड़ता है (और निश्चित रूप से औसतन):