पहली आईडी: यह सबसे चयनात्मक (यानी सबसे अनोखा) क्षेत्र है। लेकिन एक ऑटो वेतन वृद्धि क्षेत्र (या यादृच्छिक अगर अभी भी GUIDs का उपयोग करके) होने के नाते, प्रत्येक ग्राहक का डेटा प्रत्येक तालिका में फैला हुआ है। इसका मतलब यह है कि ऐसे समय होते हैं जब ग्राहक को 100 पंक्तियों की आवश्यकता होती है, और इसके लिए लगभग 100 डेटा पृष्ठों की आवश्यकता होती है जो डिस्क से (तेज नहीं) बफ़र पूल में पढ़ते हैं (10 डेटा पृष्ठों से अधिक स्थान लेते हैं)। यह डेटा पृष्ठों पर विवाद को भी बढ़ाता है क्योंकि यह अधिक बार होगा कि कई ग्राहकों को एक ही डेटा पृष्ठ को अपडेट करने की आवश्यकता होगी।
हालाँकि, आप आमतौर पर उतने पैरामीटर में नहीं चलते हैं, जितने अलग-अलग आईडी मानों के आँकड़े काफी सुसंगत हैं, उतने ही खराब / बंद कैश्ड योजना के मुद्दे। आपको सबसे इष्टतम योजनाएं नहीं मिल सकती हैं, लेकिन आपको भयानक होने की संभावना कम होगी। यह विधि अनिवार्य रूप से कम लगातार समस्याओं का लाभ प्राप्त करने के लिए सभी ग्राहकों में प्रदर्शन (थोड़ा) का बलिदान करती है।
पहले किरायेदार:यह बहुत ज्यादा चयनात्मक नहीं है। 1 मिलियन पंक्तियों में बहुत कम भिन्नता हो सकती है यदि आपके पास केवल 100 टेनेंटिड हैं। लेकिन इन प्रश्नों के आँकड़े अधिक सटीक हैं क्योंकि एसक्यूएल सर्वर को पता चल जाएगा कि टेनेंट ए के लिए एक क्वेरी 500,000 पंक्तियों को वापस खींच लेगी लेकिन टेनेंट बी के लिए एक ही क्वेरी केवल 50 पंक्तियाँ हैं। यह वह जगह है जहां मुख्य दर्द-बिंदु है। यह विधि पैरामीटर के सूँघने के मुद्दों की संभावना को बहुत बढ़ा देती है जहाँ एक संग्रहीत प्रक्रिया का पहला रन टेनेंट ए के लिए होता है और क्वेरी ऑप्टिमाइज़र के आधार पर उन आँकड़ों को देखते हुए उचित रूप से कार्य करता है और यह जानते हुए कि कुशल होने के लिए 500k पंक्तियाँ प्राप्त करने की आवश्यकता है। लेकिन जब टेनेंट बी, केवल 50 पंक्तियों के साथ चलता है, तो निष्पादन योजना अब उपयुक्त नहीं है, और वास्तव में, काफी अनुचित है। और, चूंकि डेटा को प्रमुख क्षेत्र के क्रम में नहीं डाला जा रहा है,
हालांकि, पहले टेनेंटिड के लिए एक संग्रहीत प्रक्रिया चलाने के लिए, प्रदर्शन अन्य दृष्टिकोण की तुलना में बेहतर होना चाहिए क्योंकि डेटा (कम से कम सूचकांक रखरखाव करने के बाद) शारीरिक रूप से और तार्किक रूप से आयोजित किया जाएगा ताकि कम डेटा पृष्ठों को संतुष्ट करने की आवश्यकता हो। प्रश्नों। इसका मतलब है कम भौतिक I / O, कम तार्किक रीड, एक ही डेटा पृष्ठों के लिए किरायेदारों के बीच कम विवाद, बफ़र पूल में कम बर्बाद स्थान (इसलिए बेहतर पृष्ठ जीवन प्रत्याशा) आदि।
इस बेहतर प्रदर्शन के लिए दो मुख्य लागतें हैं। पहला इतना मुश्किल नहीं है: बढ़े हुए विखंडन का मुकाबला करने के लिए आपको नियमित सूचकांक रखरखाव करना चाहिए । दूसरा थोड़ा कम मजेदार है।
बढ़े हुए सूँघने वाले मुद्दों का प्रतिकार करने के लिए, आपको किरायेदारों के बीच निष्पादन योजनाओं को अलग करना होगा। सरलीकृत दृष्टिकोण का उपयोग WITH RECOMPILE
प्रॉक्स या OPTION (RECOMPILE)
क्वेरी संकेत पर उपयोग करना है , लेकिन यह प्रदर्शन पर एक हिट है जो TenantID
पहले डालकर किए गए सभी लाभों को मिटा सकता है । जिस विधि से मैंने सबसे अच्छा काम किया है, वह है कि पैरामीटराइज्ड डायनामिक SQL का उपयोग करना sp_executesql
। डायनेमिक एसक्यूएल की आवश्यकता का कारण टेनेंटिड को क्वेरी के पाठ में समाप्त करने की अनुमति देना है, जबकि अन्य सभी विधेय जो सामान्य रूप से पैरामीटर होंगे, अभी भी पैरामीटर हैं। उदाहरण के लिए, यदि आप किसी विशेष ऑर्डर की तलाश में थे, तो आप कुछ ऐसा करेंगे:
DECLARE @GetOrderSQL NVARCHAR(MAX);
SET @GetOrderSQL = N'
SELECT ord.field1, ord.field2, etc.
FROM dbo.Orders ord
WHERE ord.TenantID = ' + CONVERT(NVARCHAR(10), @TenantID) + N'
AND ord.OrderID = @OrderID_dyn;
';
EXEC sp_executesql
@GetOrderSQL,
N'@OrderID_dyn INT',
@OrderID_dyn = @OrderID;
इसका प्रभाव यह है कि टेनेंटिड के लिए एक पुन: प्रयोज्य क्वेरी प्लान तैयार करना है जो उस विशेष टेनेंट के डेटा वॉल्यूम से मेल खाएगा। यदि वही टेनेंट ए दूसरे के लिए फिर से संग्रहीत प्रक्रिया को निष्पादित करता है, @OrderID
तो यह उस कैश्ड क्वेरी योजना का पुन: उपयोग करेगा। एक अलग किरायेदार जो कि एक ही संग्रहीत प्रक्रिया चला रहा है, एक क्वेरी पाठ उत्पन्न करेगा जो केवल TenantID के मूल्य में भिन्न था, लेकिन क्वेरी पाठ में कोई भी अंतर एक अलग योजना उत्पन्न करने के लिए पर्याप्त है। और टेनेंट बी के लिए बनाई गई योजना न केवल टेनेंट बी के लिए डेटा की मात्रा से मेल खाएगी, बल्कि यह टेनेंट बी के लिए भी अलग-अलग मूल्यों के लिए पुन: प्रयोज्य होगी @OrderID
(क्योंकि उस विधेय को अभी भी मानकीकृत किया गया है)।
इस दृष्टिकोण के नीचे हैं:
- यह एक साधारण क्वेरी में टाइप करने की तुलना में थोड़ा अधिक काम है (लेकिन सभी प्रश्नों को डायनेमिक SQL होने की आवश्यकता नहीं है, बस जो पैरामीटर को सूँघने की समस्या है उसे समाप्त करते हैं)।
- सिस्टम पर कितने किरायेदार हैं, इसके आधार पर, यह योजना कैश के आकार को बढ़ाता है क्योंकि प्रत्येक क्वेरी के लिए अब प्रति किरायेदार की 1 योजना की आवश्यकता होती है जो इसे बुला रहा है। यह एक मुद्दा नहीं हो सकता है, लेकिन कम से कम कुछ के बारे में पता होना चाहिए।
डायनेमिक SQL स्वामित्व श्रृंखला को तोड़ता है, जिसका अर्थ है कि तालिकाओं पर पढ़ने / लिखने की पहुंच को EXECUTE
संग्रहीत कार्यविधि पर अनुमति होने से नहीं माना जा सकता है । टेबल पर उपयोगकर्ता को सीधे पहुंच प्रदान करने के लिए आसान लेकिन कम सुरक्षित फिक्स है। यह निश्चित रूप से आदर्श नहीं है, लेकिन यह आमतौर पर त्वरित और आसान के लिए व्यापार-बंद है। प्रमाणपत्र-आधारित सुरक्षा का उपयोग करने के लिए अधिक सुरक्षित दृष्टिकोण है। अर्थ, एक प्रमाण पत्र बनाएं, फिर उस प्रमाणपत्र से एक उपयोगकर्ता बनाएं, जो उपयोगकर्ता को वांछित अनुमतियाँ प्रदान करता है (एक प्रमाण पत्र-आधारित उपयोगकर्ता या लॉगिन अपने आप SQL सर्वर से कनेक्ट नहीं हो सकता है), और उसके बाद डायनेमिक SQL का उपयोग करने वाली संग्रहीत कार्यविधि पर हस्ताक्षर करें। ADD हस्ताक्षर के माध्यम से एक ही प्रमाण पत्र ।
मॉड्यूल हस्ताक्षर और प्रमाण पत्र के बारे में अधिक जानकारी के लिए, कृपया देखें: ModuleSigning.Info