मल्टी-टेनेंट SQL सर्वर डेटाबेस में कंपोजिट प्राइमरी की


16

मैं एएसपी वेब एपीआई, एंटिटी फ्रेमवर्क और एसक्यूएल सर्वर / एज़्योर डेटाबेस का उपयोग करके एक बहु-किरायेदार ऐप (एकल डेटाबेस, एकल स्कीमा) का निर्माण कर रहा हूं। इस ऐप का इस्तेमाल 1000-5000 ग्राहक करेंगे। सभी तालिकाओं में TenantId(गाइड / UNIQUEIDENTIFIER) फ़ील्ड होगी। अभी, मैं सिंगल फील्ड प्राइमरी की का उपयोग करता हूं जो कि आईडी (गाइड) है। लेकिन सिर्फ आईडी क्षेत्र का उपयोग करके, मुझे यह जांचना होगा कि उपयोगकर्ता द्वारा आपूर्ति की गई डेटा सही किरायेदार के लिए / से है। उदाहरण के लिए, मेरे पास एक SalesOrderमेज है जिसमें एक CustomerIdफ़ील्ड है। जब भी उपयोगकर्ता बिक्री आदेश पोस्ट / अपडेट करते हैं, मुझे यह देखना होगा कि CustomerIdक्या वह उसी किरायेदार का है। यह बदतर हो जाता है क्योंकि प्रत्येक किरायेदार के पास कई आउटलेट हो सकते हैं। तब मैं जाँच करने के लिए है TenantIdऔर OutletId। यह वास्तव में एक रखरखाव बुरा सपना है और प्रदर्शन के लिए बुरा है।

मैं TenantIdप्राथमिक कुंजी के साथ जोड़ने के लिए सोच रहा हूँ Id। और संभवतः जोड़ें OutletId, भी। तो में प्राथमिक कुंजी SalesOrderतालिका होगा: Id, TenantId, और OutletId। इस दृष्टिकोण का नकारात्मक पक्ष क्या है? क्या समग्र कुंजी का उपयोग करने से प्रदर्शन बुरी तरह से प्रभावित होगा? क्या समग्र कुंजी क्रम मायने रखता है? क्या मेरी समस्या के बेहतर समाधान हैं?

जवाबों:


34

बड़े पैमाने पर काम करते हुए, बहु-किरायेदार प्रणाली (ग्राहकों के साथ खिलाया दृष्टिकोण 18+ सर्वरों में फैला हुआ है, प्रत्येक सर्वर में समान स्कीमा, बस अलग-अलग ग्राहक और प्रत्येक सर्वर पर प्रति सेकंड हजारों लेनदेन), मैं कह सकता हूं:

  1. कुछ लोग हैं (कुछ, कम से कम) जो "टेनडेंट" और जो भी इकाई "आईडी" दोनों के लिए आईडी के रूप में GUID की आपकी पसंद पर सहमत होंगे। लेकिन नहीं, एक अच्छा विकल्प नहीं है। एक तरफ सभी अन्य विचार, उस विकल्प को अकेले कुछ तरीकों से चोट लगेगी: विखंडन के साथ शुरू करने के लिए विखंडन, विशाल मात्रा में जगह ( डिस्क को सस्ता नहीं है जब उद्यम भंडारण के बारे में सोचते हैं - सैन - या प्रत्येक डेटा पृष्ठ के कारण लंबे समय तक होने वाले प्रश्न इसकी तुलना में कम पंक्तियों को पकड़ना या INTउससे BIGINTभी अधिक), अधिक कठिन समर्थन और रखरखाव, आदि GUID पोर्टेबिलिटी के लिए महान हैं। क्या डेटा कुछ सिस्टम में उत्पन्न होता है और फिर दूसरे में स्थानांतरित हो जाता है? यदि नहीं, तो एक अधिक कॉम्पैक्ट डेटा प्रकार (उदाहरण के लिए स्विच TINYINT, SMALLINT, INT, या यहाँ तक कि BIGINTके माध्यम से क्रमिक रूप से), और वेतन वृद्धि IDENTITYयाSEQUENCE

  2. आइटम से बाहर 1 के साथ, आपको वास्तव में हर तालिका में टेनेंटिड फ़ील्ड की आवश्यकता होगी जिसमें उपयोगकर्ता डेटा हो। इस तरह आप एक अतिरिक्त JOIN की आवश्यकता के बिना कुछ भी फ़िल्टर कर सकते हैं। इसका अर्थ यह भी है कि TenantIDJOIN कंडीशन और / या WHERE क्लॉज में क्लाइंट-डेटा टेबल के विरुद्ध सभी प्रश्नों का होना आवश्यक है । यह गारंटी देने में भी मदद करता है कि आप गलती से अलग-अलग ग्राहकों से डेटा नहीं मिलाते हैं, या किरायेदार बी से किरायेदार ए डेटा दिखाते हैं।

  3. मैं Id के साथ TenantId को प्राथमिक कुंजी के रूप में जोड़ने की सोच रहा हूं। और संभवतः OutletId को भी जोड़ें। इसलिए बिक्री आदेश तालिका में प्राथमिक कुंजी (आईडी) आईडी, टेनेंटआईड, आउटलेटलेट होगी।

    हाँ, आप क्लाइंट डेटा तालिकाओं पर अपने क्लस्टर अनुक्रमित होना चाहिए समग्र चाबियाँ, शामिल होना TenantIDऔर ID ** । यह भी सुनिश्चित करता है कि TenantIDहर गैर-संकुलित सूचकांक में है (क्योंकि इनमें क्लस्टर्ड इंडेक्स की (s) शामिल हैं) जो आपको किसी भी तरह की आवश्यकता होगी क्योंकि क्लाइंट-डेटा टेबल के खिलाफ 98.45% प्रश्नों की आवश्यकता होगी TenantID(मुख्य अपवाद तब है जब कचरा एकत्रित करने वाला पुराना डेटा आधारित है) पर CreatedDateऔर परवाह नहीं TenantID)।

    नहीं, आप OutletIDपीके जैसे एफके को शामिल नहीं करेंगे । PK को विशिष्ट रूप से पंक्ति को पहचानने की आवश्यकता है, और FK में जोड़ने से मदद नहीं मिलेगी। वास्तव में, यह डुप्लिकेट किए गए डेटा के लिए अवसरों में वृद्धि करेगा, यह मानते हुए कि ऑर्डरआईडी प्रत्येक के लिए अद्वितीय था TenantID, जैसा कि प्रत्येक के OutletIDभीतर प्रत्येक के लिए अद्वितीय है TenantID

    इसके अलावा, OutletIDपीके को जोड़ने के लिए यह सुनिश्चित करने के लिए आवश्यक नहीं है कि किरायेदार ए से आउटलेट्स को किरायेदार बी के साथ मिलाया नहीं जाता है क्योंकि पीके में सभी उपयोगकर्ता-डेटा टेबल होंगे TenantID, अर्थात TenantIDएफके में भी होगा। । उदाहरण के लिए, Outletतालिका में पीके है (TenantID, OutletID), और Orderतालिका में पीके है (TenantID, OrderID) और एफके (TenantID, OutletID)जिसमें से Outletतालिका पर पीके का संदर्भ है । उचित रूप से परिभाषित FKs किरायेदार डेटा को रुक-रुक कर होने से रोकेंगे।

  4. समग्र कुंजी क्रम मायने रखता है?

    खैर, यहाँ है जहाँ यह मज़ा आता है। कुछ बहस है कि किस क्षेत्र में पहले आना चाहिए। अच्छे अनुक्रमों को डिजाइन करने के लिए "विशिष्ट" नियम प्रमुख क्षेत्र होने के लिए सबसे अधिक चयनात्मक क्षेत्र चुनना है। TenantID, इसकी प्रकृति से, सबसे चयनात्मक क्षेत्र नहीं होगा ; IDक्षेत्र ज़्यादातर चुनिंदा क्षेत्र है। यहाँ कुछ विचार हैं:

    • पहली आईडी: यह सबसे चयनात्मक (यानी सबसे अनोखा) क्षेत्र है। लेकिन एक ऑटो वेतन वृद्धि क्षेत्र (या यादृच्छिक अगर अभी भी 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
         

    कृपया इस निर्णय से उत्पन्न आँकड़ों को कम करने वाले मुद्दों से संबंधित अतिरिक्त विषयों के लिए अंत में UPDATE अनुभाग देखें ।


** व्यक्तिगत रूप से, मैं वास्तव में हर मेज पर PK फ़ील्ड के नाम के लिए "ID" का उपयोग करना पसंद नहीं करता क्योंकि यह सार्थक नहीं है, और यह FKs के अनुरूप नहीं है क्योंकि PK हमेशा "ID" है और बच्चे की तालिका में फ़ील्ड है मूल तालिका नाम शामिल करें। उदाहरण के लिए: Orders.ID-> OrderItems.OrderID। मुझे उस डेटा मॉडल से निपटना बहुत आसान लगता है जिसके पास: Orders.OrderID-> है OrderItems.OrderID। यह अधिक पठनीय है, और आपको "अस्पष्ट कॉलम संदर्भ" त्रुटि :-) प्राप्त होने की संख्या में कटौती होगी।


अपडेट करें

  • चाहेंगे OPTIMIZE FOR UNKNOWN क्वेरी सुझाव समग्र पी के दोनों आदेश के साथ (SQL सर्वर में पेश 2008) मदद करता है?

    ज़रुरी नहीं। यह विकल्प पैरामीटर सूँघने के मुद्दों के आसपास मिलता है, लेकिन यह केवल एक समस्या को दूसरे के साथ बदल देता है। इस मामले में, संग्रहीत प्रक्रिया या पैरामीटर क्वेरी के प्रारंभिक रन के पैरामीटर मानों के लिए सांख्यिकीय जानकारी को याद करने के बजाय (जो कुछ के लिए निश्चित रूप से महान है, लेकिन कुछ के लिए संभावित औसत दर्जे का है, और कुछ के लिए संभावित रूप से भयानक है), यह एक सामान्य का उपयोग करता है पंक्ति गणना का अनुमान लगाने के लिए डेटा वितरण का आँकड़ा। यह हिट-या-मिस है, क्योंकि कितने (और किस डिग्री तक) प्रश्नों का सकारात्मक, नकारात्मक या बिल्कुल भी प्रभावित नहीं होगा। कम से कम पैरामीटर के साथ कुछ प्रश्नों को सूँघने से लाभ की गारंटी थी। यदि आपके सिस्टम में व्यापक रूप से विविध डेटा संस्करणों के साथ किरायेदार हैं, तो यह संभवतः सभी प्रश्नों के लिए प्रदर्शन को नुकसान पहुंचा सकता है।

    यह विकल्प इनपुट मापदंडों को स्थानीय चर के लिए कॉपी करने और फिर क्वेरी में स्थानीय चर का उपयोग करने के रूप में एक ही बात को पूरा करता है (मैंने यह परीक्षण किया है लेकिन उसके लिए कोई जगह नहीं है)। अतिरिक्त जानकारी इस ब्लॉग पोस्ट में पाई जा सकती है: http://www.brentozar.com/archive/2013/06/optimize-for-unknown-sql-server-parameter-sniffing/ । टिप्पणियों को पढ़कर, डैनियल पेपरमैन्स डायनामिक एसक्यूएल के उपयोग के बारे में एक निष्कर्ष पर पहुंचा, जिसमें सीमित भिन्नता है।

  • अगर आईडी क्लस्टर किए गए इंडेक्स में अग्रणी क्षेत्र है, तो क्या यह (टेनेंटिड, आईडी), या सिर्फ (टेनेंटिड) पर एक गैर-क्लस्टर इंडेक्स रखने में मदद करेगा या एक टेनेंट की कई पंक्तियों को संसाधित करने वाले प्रश्नों के सटीक आंकड़े होगा?

    हाँ, यह मदद करेगा। जिस बड़ी प्रणाली का मैंने वर्षों से काम करने का उल्लेख किया था, वह IDENTITYक्षेत्र को अग्रणी क्षेत्र के रूप में रखने के सूचकांक के डिजाइन पर आधारित थी क्योंकि यह अधिक चयनात्मक था और पैरामीटर सूँघने के मुद्दों को कम करता था। हालांकि, जब हमें किसी विशेष टेनेंट के डेटा के एक अच्छे हिस्से के खिलाफ संचालन की आवश्यकता होती है, तो प्रदर्शन नहीं हुआ। वास्तव में, सभी डेटा को नए डेटाबेस में स्थानांतरित करने के लिए एक परियोजना को रोकना पड़ा क्योंकि सैन नियंत्रक थ्रूपुट के संदर्भ में अधिकतम हो गए। यह तय था कि सभी टेनेंट डेटा टेबल में नॉन-क्लस्टर्ड इंडेक्स को जोड़कर सिर्फ (टेनेंटिड) किया जाए। (टेनेंटिड, आईडी) करने की आवश्यकता नहीं है क्योंकि आईडी पहले से ही क्लस्टर्ड इंडेक्स में है, इसलिए नॉन-क्लस्टर्ड इंडेक्स की आंतरिक संरचना स्वाभाविक रूप से (टेनेंटिड, आईडी) थी।

    हालांकि इसने टेनेंटिड-आधारित प्रश्नों को अधिक कुशलता से करने में सक्षम होने के तात्कालिक मुद्दे को हल किया, वे अभी भी उतने कुशल नहीं थे जितना कि यदि यह उसी क्रम में थे तो यह क्लस्टर इंडेक्स हो सकता था। और, अब हमारे पास हर मेज पर एक और सूचकांक था । सैन स्पेस की मात्रा को हम बढ़ा रहे थे, हमारे बैकअप के आकार में वृद्धि की, बैकअप को पूरा होने में अधिक समय लगा, अवरुद्ध और गतिरोध की क्षमता में वृद्धि, प्रदर्शन INSERTऔर DELETEसंचालन में कमी आदि।

    और हम अभी भी कई डेटा पेजों में फैले टेनेंट के डेटा के सामान्य अक्षमता के साथ बाकी थे, कई अन्य टेनेंट के डेटा के साथ इंटरमिक्स किया गया। जैसा कि मैंने ऊपर उल्लेख किया है, इससे इन पृष्ठों पर विवाद की मात्रा बढ़ जाती है, और यह बफ़र पूल को बहुत सारे डेटा पृष्ठों के साथ भर देता है, जिनमें 1 या 2 उपयोगी पंक्तियाँ होती हैं, खासकर जब उन पृष्ठों की कुछ पंक्तियाँ ग्राहकों के लिए थीं निष्क्रिय थे लेकिन अभी तक कचरा एकत्र नहीं किया गया था। इस दृष्टिकोण में बफ़र पूल में डेटा पृष्ठों के पुन: उपयोग की बहुत कम संभावना है, इसलिए हमारा पृष्ठ जीवन प्रत्याशा बहुत कम था। और इसका मतलब है कि अधिक पृष्ठों को लोड करने के लिए डिस्क पर वापस जाने में अधिक समय।


2
क्या आपने इस समस्या स्थान में UNKNOWN के लिए OPTIMIZE पर विचार या परीक्षण किया है? बस उत्सुक।
RLF

1
@RLF हाँ, हमने उस विकल्प पर शोध किया, और यह कम से कम कोई बेहतर नहीं होना चाहिए, और संभवतः इससे भी बदतर हो सकता है, सबसे कम प्रदर्शन की तुलना में हम पहले पहचान क्षेत्र होने से कम थे। मुझे याद नहीं है कि मैं इसे कहाँ पढ़ता हूँ, लेकिन यह माना जाता है कि यह "औसत" आँकड़े देता है जो एक स्थानीय चर के लिए इनपुट परम को पुन: असाइन करता है। लेकिन यह लेख इस विकल्प में क्यों जाता है कि समस्या वास्तव में हल नहीं होती है: brentozar.com/archive/2013/06/ ... टिप्पणियों को पढ़ते हुए, डैनियल पेपरमैन एक समान निष्कर्ष पर आए: डायनेमिक SQL सीमित विविधता के साथ :)
सोलोमन रुट्ज़की

3
क्या होगा यदि क्लस्टर इंडेक्स चालू है (ID, TenantID)और आप एक गैर-क्रस्टेड इंडेक्स भी बनाते हैं (TenantID, ID), या केवल उन (TenantID)प्रश्नों के लिए सटीक आंकड़े हैं जो एक एकल किरायेदार की अधिकांश पंक्तियों को संसाधित करते हैं?
व्लादिमीर बारानोव

1
@VladimirBaranov उत्कृष्ट सवाल। मैंने उत्तर के अंत की ओर एक नए अद्यतन अनुभाग में इसे संबोधित किया है :-)।
सोलोमन रटज़की

4
प्रत्येक ग्राहक के लिए योजना बनाने के लिए गतिशील एसक्यूएल के बारे में अच्छी बात ।
मैक्स वर्नोन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.