LOB_DATA, धीमी तालिका स्कैन और कुछ I / O प्रश्न


19

मेरे पास स्तंभों में से एक के साथ एक बड़ी तालिका है जिसमें XML डेटा का एक औसत आकार है जिसमें XML प्रविष्टि का औसत आकार ~ 15 किलोबाइट है। अन्य सभी कॉलम नियमित इन्ट्स, बिगिंट्स, GUID आदि हैं। कुछ ठोस संख्याएँ हैं, मान लें कि तालिका में एक लाख पंक्तियाँ हैं और आकार में ~ 15 GB है।

मैंने जो देखा वह यह है कि यदि मैं सभी कॉलमों का चयन करना चाहता हूं तो यह तालिका डेटा का चयन करने के लिए वास्तव में धीमी है। जब मैं करता हूं

SELECT TOP 1000 * FROM TABLE

डिस्क से डेटा को पढ़ने में लगभग 20-25 सेकंड लगते हैं - भले ही मैं परिणाम पर कोई आदेश नहीं देता हूं। मैं कोल्ड कैश (यानी बाद DBCC DROPCLEANBUFFERS) के साथ क्वेरी चलाता हूं । यहाँ IO आँकड़े परिणाम हैं:

स्कैन काउंट 1, लॉजिकल रीड 3636, फिजिकल रीड 24, रीड-फॉरवर्ड रीड 7191, लोब लॉजिकल रीड 7924, लोब फिजिकल रीड 1690, लोब रीड-फॉरवर्ड रीड 3968।

यह ~ 15 एमबी डेटा को पकड़ लेता है। निष्पादन योजना क्लस्टर्ड इंडेक्स स्कैन दिखाती है जैसा कि मुझे उम्मीद है।

मेरे प्रश्नों के अलावा डिस्क पर कोई आईओ नहीं चल रहा है; मैंने यह भी जांचा है कि क्लस्टर इंडेक्स विखंडन 0% के करीब है। यह एक उपभोक्ता-ग्रेड SATA ड्राइव है, हालांकि मुझे अभी भी लगता है कि SQL सर्वर ~ 100-150 MB / मिनट से अधिक तेज़ी से तालिका को स्कैन करने में सक्षम होगा।

XML फ़ील्ड की उपस्थिति के कारण अधिकांश टेबल डेटा LOB_DATA पृष्ठों पर स्थित होता है (वास्तव में ~ टेबल पृष्ठों का 90% LOB_DATA है)।

मुझे लगता है कि मेरा प्रश्न है - क्या मैं यह सोचने में सही हूं कि LOB_DATA पृष्ठ न केवल उनके आकार के कारण धीमी स्कैन का कारण बन सकते हैं, बल्कि इसलिए भी क्योंकि SQL सर्वर तालिका में बहुत सारे LOB_DATA पृष्ठों के प्रभावी रूप से क्लस्टर इंडेक्स को स्कैन नहीं कर सकता है?

और भी मोटे तौर पर - क्या ऐसी तालिका संरचना / डेटा पैटर्न के लिए उचित माना जाता है? Filestream का उपयोग करने के लिए सिफारिशें आमतौर पर बहुत बड़े क्षेत्र का आकार देती हैं, इसलिए मैं वास्तव में उस मार्ग पर नहीं जाना चाहता। मुझे वास्तव में इस विशेष परिदृश्य के बारे में कोई अच्छी जानकारी नहीं मिली है।

मैं XML कम्प्रेशन की ओर सोच रहा हूँ, लेकिन इसे क्लाइंट पर या SQLCLR के साथ करने की आवश्यकता है और सिस्टम में लागू करने के लिए काफी काम की आवश्यकता होगी।

मैंने कम्प्रेशन की कोशिश की, और चूंकि XML अतिरेक हैं, इसलिए मैं (ac # ऐप में) XML को 20KB से ~ 2.5KB तक कम कर सकता हूं और VARBINARY कॉलम में स्टोर कर सकता हूं, LOB डेटा पेज के उपयोग को रोक सकता है। यह गति मेरे परीक्षणों में 20x बार चयन करती है।


एलेक्स: यकीन नहीं है कि अगर आपने मेरे उत्तर से संबंधित चर्चा देखी (लिंक मेरे उत्तर के नीचे टिप्पणी में है), लेकिन मैं आपके परिदृश्य को पुन: प्रस्तुत करने में सक्षम था। मैंने आपके विवरण के लिए एक मेल मिलान (जितना मुझे जानकारी थी) के लिए पॉपुलेट किया और मुझे I / O आँकड़े मिले जो बहुत समान हैं। सिवाय, "एलओबी फिजिकल रीड्स" कभी भी करीब नहीं थे। इसलिए मैं सोच रहा था कि क्या आपने XML (लेकिन अन्य कॉलम नहीं) और / या आपकी डेटा फ़ाइलों का भौतिक विखंडन किया है। मुझे अभी भी आपकी तालिका की DDL और प्रत्येक डेटा फ़ाइल के लिए आपकी ऑटो-वृद्धि सेटिंग प्राप्त करने में कोई आपत्ति नहीं होगी, और क्या आप अपनी डेटा फ़ाइलों को सिकोड़ते हैं?
सोलोमन रटज़की

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

(जारी) मैंने सवाल पूछने से पहले फाइलों के भौतिक विखंडन की जाँच की, और अंतर्निहित विंडोज टूल ने सोचा कि यह ठीक है, इसलिए मैंने इसे आगे नहीं देखा। ऑटो-ग्रोथ डिफ़ॉल्ट है, 1 एमबी तक मुझे विश्वास है, और डेटा फ़ाइलों को सिकुड़ा नहीं गया है।
अलेक्जेंडर शेल्मिन

मेरे विशेष मामले में शीर्ष 1000 का चयन करें। मैं निश्चित रूप से समझता हूं कि यह एक बुरा अभ्यास माना जाता है, हालांकि कुछ एप्लिकेशन डिज़ाइन निर्णय लंबे समय तक रहने के बाद वास्तव में बदलना मुश्किल है। चयन * मूल रूप से हमारे ऐप में विभिन्न घटकों के बीच एक क्रॉस-डेटाबेस प्रतिकृति रणनीति के रूप में उपयोग किया जाता है। इसके पक्ष में हैं, उदाहरण के लिए हम मक्खी पर डेटा / स्कीमा के साथ बहुत सारी मनमानी कर सकते हैं, जो अंतर्निहित प्रतिकृति तकनीकों के साथ कठिन होगा, लेकिन यह अपनी समस्याओं के साथ आता है।
अलेक्जेंडर शेल्मिन

एलेक्स, SELECT *अगर आप XML डेटा की जरूरत नहीं है तो यह समस्या नहीं है। यह केवल एक मुद्दा है यदि आप XML डेटा नहीं चाहते हैं, तो उस स्थिति में डेटा वापस पाने के लिए क्वेरी को धीमा क्यों करें जिसका आप उपयोग नहीं करते हैं? मैंने XML के अद्यतनों के बारे में पूछा कि क्या LOB पृष्ठों पर विखंडन सही नहीं बताया जा रहा है। यही कारण है कि मैंने अपने जवाब में पूछा था कि आपने यह कैसे निर्धारित किया कि क्लस्टर इंडेक्स खंडित नहीं था? क्या आप अपने द्वारा चलाए गए आदेश को प्रदान कर सकते हैं? और क्या आपने Clustered Index पर पूर्ण REBUILD किया है? (जारी)
सोलोमन रटज़की

जवाबों:


11

XML फ़ील्ड की उपस्थिति के कारण अधिकांश टेबल डेटा LOB_DATA पृष्ठों पर स्थित होता है (वास्तव में ~ टेबल पृष्ठों का 90% LOB_DATA है)।

केवल तालिका में XML कॉलम होने से इसका प्रभाव नहीं होता है। यह XML डेटा की उपस्थिति है, जो कुछ शर्तों के तहत , पंक्ति के डेटा के कुछ हिस्से को LOB_DATA पृष्ठों पर पंक्ति से संग्रहीत करने का कारण बनता है। और जब एक (या शायद कई ;-) यह तर्क दे सकता है कि XMLकॉलम का तात्पर्य है कि स्तंभ वास्तव में XML डेटा होगा, यह गारंटी नहीं है कि XML डेटा को पंक्ति से संग्रहीत करने की आवश्यकता होगी: जब तक कि पंक्ति बहुत पहले से ही भर नहीं जाती है किसी भी XML डेटा के बाहर, छोटे दस्तावेज़ (8000 बाइट तक) पंक्ति में फिट हो सकते हैं और कभी भी LOB_ATA डेटा पृष्ठ पर नहीं जाते हैं।

क्या मैं यह सोचने में सही हूं कि LOB_DATA पृष्ठ न केवल उनके आकार के कारण धीमी गति से स्कैन का कारण बन सकते हैं, बल्कि इसलिए भी क्योंकि SQL सर्वर तालिका में बहुत सारे LOB_DATA पृष्ठों के प्रभावी रूप से क्लस्टर इंडेक्स को स्कैन नहीं कर सकता है?

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

इसलिए हम पहले से ही जानते हैं कि SELECT TOP 1000 *परीक्षण केवल एक पंक्ति में 8k डेटा पृष्ठों की एक श्रृंखला नहीं पढ़ रहा था, बल्कि प्रत्येक पंक्ति में अन्य स्थानों पर कूद रहा था । उस एलओबी डेटा की सटीक संरचना इस बात पर आधारित हो सकती है कि यह कितना बड़ा है। यहां दिखाए गए शोध के आधार पर (अधिकतम के लिए LOB पॉइंटर का आकार क्या है) प्रकार जैसे कि वर्चर, वर्ब, आदि। ), दो प्रकार के ऑफ-पंक्ति एलओबी आवंटन हैं:

  1. इनलाइन रूट - 8001 से 40,000 (वास्तव में 42,000) बाइट्स, अंतरिक्ष अनुमति के बीच के डेटा के लिए, 1 से 5 पॉइंटर्स (24 - 72 बाइट्स) होंगे जो सीधे LOB पेज (ओं) को इंगित करते हैं।
  2. TEXT_TREE - 42,000 से अधिक बाइट्स के डेटा के लिए, या यदि 1 से 5 पॉइंटर्स-इन-रो फिट नहीं हो सकते हैं, तो LOB पृष्ठों (यानी "के लिए पॉइंटर्स की सूची के शुरुआती पृष्ठ पर सिर्फ 24 बाइट पॉइंटर होगा।" text_tree "पेज)।

इन दो स्थितियों में से एक हर बार जब आप एलओबी डेटा प्राप्त करते हैं जो 8000 बाइट्स से अधिक होता है या सिर्फ इन-पंक्ति में फिट नहीं होता है। मैंने PasteBin.com ( LOB आवंटन और परीक्षण पढ़ने के लिए टी-एसक्यूएल स्क्रिप्ट ) पर एक परीक्षण स्क्रिप्ट पोस्ट की है जो 3 प्रकार के LOB आवंटन (डेटा के आकार के आधार पर) के साथ-साथ उनमें से प्रत्येक के तार्किक या प्रभाव पर असर दिखाता है। भौतिक पढ़ता है। आपके मामले में, यदि XML डेटा वास्तव में प्रति पंक्ति 42,000 बाइट्स से कम है, तो इसमें से कोई भी (या इसके बहुत कम) कम से कम कुशल TEXT_TREE संरचना में होना चाहिए।

यदि आप परीक्षण करना चाहते हैं कि SQL सर्वर उस क्लस्टर इंडेक्स को कितनी जल्दी स्कैन कर सकता है, SELECT TOP 1000लेकिन उस XML कॉलम को शामिल करते हुए एक या अधिक कॉलम निर्दिष्ट करें। यह आपके परिणामों को कैसे प्रभावित करता है? यह काफी तेज होना चाहिए।

क्या ऐसी तालिका संरचना / डेटा पैटर्न के लिए उचित माना जाता है?

यह देखते हुए कि हमारे पास वास्तविक तालिका संरचना और डेटा पैटर्न का अधूरा विवरण है, कोई भी उत्तर उन गुम विवरणों के आधार पर इष्टतम नहीं हो सकता है। इसे ध्यान में रखते हुए, मैं कहूंगा कि आपकी तालिका संरचना या डेटा पैटर्न के बारे में स्पष्ट रूप से अनुचित कुछ भी नहीं है।

मैं 20KB से ~ 2.5KB तक XML को (ac # ऐप में) संपीड़ित कर सकता हूं और LOB डेटा पृष्ठों के उपयोग को रोकने के लिए इसे VARBINARY कॉलम में संग्रहीत कर सकता हूं। यह गति मेरे परीक्षणों में 20x बार चयन करती है।

इसने सभी कॉलमों का चयन किया, या यहां तक ​​कि सिर्फ XML डेटा (अब VARBINARY) में तेजी से, लेकिन यह वास्तव में उन प्रश्नों को नुकसान पहुंचाता है जो "XML" डेटा का चयन नहीं करते हैं। मान लें कि आपके पास अन्य स्तंभों में लगभग 50 बाइट्स हैं और FILLFACTOR100 में से एक है, तो:

  • कोई संपीड़न नहीं: 15k XMLडेटा में 2 LOB_DATA पृष्ठों की आवश्यकता होती है, जिसके लिए इनलाइन रूट के लिए 2 पॉइंटर्स की आवश्यकता होती है। पहला पॉइंटर 24 बाइट्स का है और दूसरा 12 का है, जिसमें XML डेटा के लिए कुल 36 बाइट्स हैं। कुल पंक्ति का आकार 86 बाइट्स है, और आप 8060 बाइट डेटा पेज पर उन पंक्तियों में से 93 को फिट कर सकते हैं। इसलिए, 1 मिलियन पंक्तियों के लिए 10,753 डेटा पृष्ठों की आवश्यकता होती है।

  • कस्टम संपीड़न: 2.5k VARBINARYडेटा पंक्ति में फिट होगा। कुल पंक्ति का आकार 2610 (2.5 * 1024 = 2560) बाइट्स है, और आप 8060 बाइट डेटा पेज पर उन पंक्तियों में से केवल 3 को ही फिट कर सकते हैं। इसलिए, 1 मिलियन पंक्तियों के लिए 333,334 डेटा पृष्ठों की आवश्यकता होती है।

एर्गो, क्लस्टर्ड इंडेक्स के लिए डेटा पन्नों में 30 गुना वृद्धि में कस्टम संपीड़न परिणामों को लागू करता है । मतलब, क्लस्टर्ड इंडेक्स स्कैन का उपयोग करने वाले सभी प्रश्नों में अब पढ़ने के लिए लगभग 322,500 अधिक डेटा पृष्ठ हैं। कृपया इस प्रकार के कम्प्रेशन करने के अतिरिक्त रेमूलेशन के लिए नीचे विस्तृत सेक्शन देखें।

मैं के प्रदर्शन के आधार पर किसी भी रिफैक्टरिंग करने के खिलाफ सावधानी बरतूँगा SELECT TOP 1000 *। यह एक क्वेरी होने की संभावना नहीं है कि आवेदन भी जारी करेगा, और संभावित अनावश्यक अनुकूलन (ओं) के लिए एकमात्र आधार के रूप में उपयोग नहीं किया जाना चाहिए।

अधिक विस्तृत जानकारी और अधिक परीक्षणों की कोशिश करने के लिए, कृपया नीचे अनुभाग देखें।


इस प्रश्न का निश्चित उत्तर नहीं दिया जा सकता है, लेकिन हम कम से कम कुछ प्रगति कर सकते हैं और अतिरिक्त शोध का सुझाव दे सकते हैं ताकि हमें सटीक मुद्दे का पता लगाने में मदद मिल सके (आदर्श रूप से साक्ष्य के आधार पर)।

हम क्या जानते हैं:

  1. तालिका में लगभग 1 मिलियन पंक्तियाँ हैं
  2. टेबल का आकार लगभग 15 जीबी है
  3. टेबल एक शामिल XMLस्तंभ और प्रकार के कई अन्य स्तंभों: INT, BIGINT, UNIQUEIDENTIFIER, "आदि"
  4. XMLकॉलम "आकार" औसतन लगभग 15k है
  5. दौड़ने के बाद DBCC DROPCLEANBUFFERS, निम्नलिखित क्वेरी को पूरा करने में 20 - 25 सेकंड लगते हैं:SELECT TOP 1000 * FROM TABLE
  6. क्लस्टर सूचकांक को स्कैन किया जा रहा है
  7. क्लस्टर किए गए सूचकांक पर विखंडन 0% के करीब है

हम क्या सोचते हैं हम जानते हैं:

  1. इन प्रश्नों के बाहर कोई अन्य डिस्क गतिविधि नहीं। क्या आपको यकीन है? यहां तक ​​कि अगर कोई अन्य उपयोगकर्ता प्रश्न नहीं हैं, तो क्या पृष्ठभूमि संचालन हो रहा है? क्या SQL सर्वर पर बाहरी प्रक्रियाएं एक ही मशीन पर चल रही हैं जो कुछ IO को ले जा सकती हैं? वहाँ नहीं हो सकता है, लेकिन यह पूरी तरह से प्रदान की गई जानकारी के आधार पर स्पष्ट नहीं है।
  2. 15 एमबी XML डेटा वापस किया जा रहा है। यह संख्या किस पर आधारित है? प्रति पंक्ति XML डेटा के औसत से 1000 पंक्तियों से प्राप्त अनुमान प्रति पंक्ति 15k है? या उस क्वेरी के लिए जो प्राप्त हुआ था उसका प्रोग्रामेटिक एकत्रीकरण? यदि यह केवल एक अनुमान है, तो मैं इस पर भरोसा नहीं करूंगा क्योंकि XML डेटा का वितरण उस तरह से भी नहीं हो सकता है जो एक साधारण औसत द्वारा निहित होता है।
  3. XML संपीड़न मदद कर सकता है। आप .NET में कम्प्रेशन कैसे करेंगे? GZipStream या DeflateStream वर्ग के माध्यम से ? यह एक शून्य-लागत विकल्प नहीं है। यह निश्चित रूप से कुछ डेटा को बड़े प्रतिशत से संपीड़ित करेगा, लेकिन इसमें अधिक सीपीयू की भी आवश्यकता होगी क्योंकि आपको हर बार डेटा को संपीड़ित / डिकम्प्रेस करने के लिए एक अतिरिक्त प्रक्रिया की आवश्यकता होगी। यह योजना पूरी तरह से आपकी क्षमता को दूर कर देगी:

    • क्वेरी के माध्यम से XML डेटा .nodes, .value, .query, और .modifyएक्सएमएल कार्य करता है।
    • XML डेटा को इंडेक्स करें।

      कृपया ध्यान रखें (जब से आपने उल्लेख किया है कि XML "अत्यधिक अनावश्यक" है) कि XMLडेटाटाइप पहले से ही इसमें अनुकूलित है कि यह एक शब्दकोश में तत्व और विशेषता नामों को संग्रहीत करता है, प्रत्येक आइटम के लिए एक पूर्णांक सूचकांक आईडी निर्दिष्ट करता है, और फिर उस पूर्णांक आईडी का उपयोग करता है पूरे दस्तावेज़ में (इसलिए यह प्रत्येक उपयोग के अनुसार पूरा नाम नहीं दोहराता है, और न ही इसे तत्वों के समापन के रूप में फिर से दोहराता है)। वास्तविक डेटा में बाहरी सफेद स्थान भी हटा दिया गया है। यही कारण है कि एक्सएमएल दस्तावेज़ निकाले जाने से उनकी मूल संरचना बरकरार नहीं रहती है और खाली तत्व क्यों निकाले जाते हैं, <element />भले ही वे अंदर गए हों<element></element>। तो GZip (या कुछ और) के माध्यम से संपीड़ित करने से कोई भी लाभ केवल तत्व और / या विशेषता मानों को संपीड़ित करने से मिलेगा, जो कि एक बहुत छोटा सतह क्षेत्र है जिसे सबसे अधिक उम्मीद की जा सकती है, और सबसे अधिक संभावना है कि नुकसान के लायक नहीं है क्षमताओं के रूप में सीधे ऊपर उल्लेख किया है।

      कृपया यह भी ध्यान रखें कि XML डेटा को संपीड़ित करने और VARBINARY(MAX)परिणाम को संग्रहीत करने से LOB की पहुंच समाप्त नहीं होगी, यह इसे कम कर देगा। पंक्ति के शेष डेटा के आकार के आधार पर, संपीड़ित मान पंक्ति में फिट हो सकता है, या इसके लिए अभी भी LOB पृष्ठों की आवश्यकता हो सकती है।

यह जानकारी, जबकि उपयोगी है, लगभग पर्याप्त नहीं है। क्वेरी प्रदर्शन को प्रभावित करने वाले बहुत सारे कारक हैं, इसलिए हमें जो कुछ चल रहा है उसकी अधिक विस्तृत तस्वीर की आवश्यकता है।

हम क्या नहीं जानते, लेकिन इसके लिए आवश्यक है:

  1. SELECT *पदार्थ का प्रदर्शन क्यों होता है? क्या यह एक पैटर्न है जिसे आप कोड में उपयोग करते हैं। यदि हां, तो क्यों?
  2. केवल XML कॉलम के चयन का प्रदर्शन क्या है? क्या आँकड़े और समय यदि आप बस कर रहे हैं SELECT TOP 1000 XmlColumn FROM TABLE;:?
  3. इन 1000 पंक्तियों को वापस करने में 20 - 25 सेकंड का समय नेटवर्क कारकों (वायर के पार डेटा प्राप्त करने) से संबंधित है, और क्लाइंट कारकों से कितना संबंधित है (प्रतिपादन है कि लगभग 15 एमबी प्लस बाकी गैर- एसएसएमएस में ग्रिड में एक्सएमएल डेटा, या संभवतः डिस्क पर बचत)?

    ऑपरेशन के इन दो पहलुओं को बाहर निकालना कभी-कभी डेटा को वापस नहीं करने के द्वारा किया जा सकता है। अब, कोई अस्थायी तालिका या तालिका चर में चयन करने के लिए सोच सकता है, लेकिन यह सिर्फ कुछ नए चर (यानी डिस्क I / O के लिए tempdb, लेन-देन लॉग लिखता है, tempdb डेटा और / या लॉग फ़ाइल की संभावित ऑटो-वृद्धि की आवश्यकता होगी बफ़र पूल में स्थान, आदि)। वे सभी नए कारक वास्तव में क्वेरी समय बढ़ा सकते हैं। इसके बजाय, मैं आमतौर पर स्तंभों को चर (उपयुक्त डेटाटाइप का; नहीं SQL_VARIANT) में संग्रहीत करता हूं जो प्रत्येक नई पंक्ति (यानी SELECT @Column1 = tab.Column1,...) के साथ ओवरराइट हो जाते हैं ।

    हालांकि , के रूप में यह DBA.StackExchange क्यू एंड ए में @PaulWhite द्वारा बताया गया, तार्किक अलग पढ़ता है जब एक ही LOB डेटा तक पहुँचने pastebin पर पोस्ट मेरे अपने के अतिरिक्त अनुसंधान के साथ, ( टी SQL स्क्रिप्ट LOB पढ़ता के लिए विभिन्न परिदृश्यों का परीक्षण ) , LOBs लगातार के बीच पहुँचा नहीं कर रहे हैं SELECT, SELECT INTO, SELECT @XmlVariable = XmlColumn, SELECT @XmlVariable = XmlColumn.query(N'/'), और SELECT @NVarCharVariable = CONVERT(NVARCHAR(MAX), XmlColumn)। तो हमारे विकल्प यहाँ कुछ अधिक सीमित हैं, लेकिन यहाँ वही किया जा सकता है:

    1. SSMS या SQLCMD.EXE में SQL सर्वर चलाने वाले सर्वर पर क्वेरी को निष्पादित करके नेटवर्क मुद्दों को नियमित करें।
    2. क्वेरी विकल्प -> परिणाम -> ग्रिड पर जाएं और "निष्पादन के बाद परिणामों को छोड़ें" के विकल्प की जांच करके SSMS में क्लाइंट मुद्दों को नियमबद्ध करें। कृपया ध्यान दें कि यह विकल्प संदेशों सहित सभी आउटपुट को रोक देगा, लेकिन प्रत्येक पंक्ति में मेमोरी को आवंटित करने और फिर इसे ग्रिड में ड्रा करने के लिए SSMS को लगने वाले समय को नियंत्रित करने के लिए उपयोगी हो सकता है।
      वैकल्पिक रूप से, आप SQLCMD.EXE के माध्यम से क्वेरी को निष्पादित कर सकते हैं और आउटपुट को कहीं भी जाने के लिए निर्देशित कर सकते हैं -o NUL::।
  4. क्या इस क्वेरी से कोई प्रतीक्षा प्रकार जुड़ा हुआ है? यदि हाँ, तो वह प्रतीक्षा प्रकार क्या है?
  5. वापस किए जा रहे कॉलम के लिए वास्तविक डेटा आकार क्या है ? संपूर्ण तालिका में उस स्तंभ का औसत आकार वास्तव में मायने नहीं रखता है यदि "TOP 1000" पंक्तियों में कुल डेटा का एक बड़ा हिस्सा हो । यदि आप TOP 1000 पंक्तियों के बारे में जानना चाहते हैं, तो उन पंक्तियों को देखें। कृपया निम्नलिखित चलाएं:XMLXML

    SELECT TOP 1000 tab.*,
           SUM(DATALENGTH(tab.XmlColumn)) / 1024.0 AS [TotalXmlKBytes],
           AVG(DATALENGTH(tab.XmlColumn)) / 1024.0 AS [AverageXmlKBytes]
           STDEV(DATALENGTH(tab.XmlColumn)) / 1024.0 AS [StandardDeviationForXmlKBytes]
    FROM   SchemaName.TableName tab;
  6. सटीक तालिका स्कीमा। कृपया सभी अनुक्रमणिका सहित पूरा CREATE TABLE विवरण प्रदान करें ।
  7. प्रश्न योजना? क्या ऐसा कुछ है जिसे आप पोस्ट कर सकते हैं? यह जानकारी शायद कुछ भी नहीं बदलेगी, लेकिन यह जानना बेहतर है कि यह अनुमान लगाने की तुलना में नहीं होगा कि यह गलत नहीं होगा;;
  8. क्या डेटा फ़ाइल पर भौतिक / बाहरी विखंडन है? हालांकि यह एक बड़ा कारक नहीं हो सकता है, क्योंकि आप "उपभोक्ता-ग्रेड एसएटीए" का उपयोग कर रहे हैं और एसएसडी या यहां तक ​​कि सुपर-एक्सपेंसिव एसएटीए का उपयोग नहीं कर रहे हैं, उप-क्रमिक रूप से ऑर्डर किए गए सेक्टरों का प्रभाव अधिक ध्यान देने योग्य होगा, विशेष रूप से उन क्षेत्रों की संख्या के रूप में जिसे पढ़ने की आवश्यकता बढ़ जाती है।
  9. निम्नलिखित क्वेरी के सटीक परिणाम क्या हैं :

    SELECT * FROM sys.dm_db_index_physical_stats(DB_ID(),
                              OBJECT_ID(N'dbo.SchemaName.TableName'), 1, 0, N'LIMITED');

अपडेट करें

मेरे साथ यह हुआ कि मुझे इस परिदृश्य को पुन: पेश करने की कोशिश करनी चाहिए कि क्या मैं समान व्यवहार का अनुभव करता हूं। इसलिए, मैंने कई स्तंभों के साथ एक तालिका बनाई (प्रश्न में अस्पष्ट वर्णन के समान), और फिर इसे 1 मिलियन पंक्तियों के साथ आबाद किया, और XML कॉलम में प्रति पंक्ति लगभग 15k डेटा है (नीचे कोड देखें)।

मैंने जो पाया वह यह है कि SELECT TOP 1000 * FROM TABLEपहली बार 8 सेकंड में पूरा किया और उसके बाद 2 - 4 सेकंड हर बार (हाँ, क्वेरी के DBCC DROPCLEANBUFFERSप्रत्येक रन से पहले निष्पादित SELECT *)। और मेरा कई साल पुराना लैपटॉप तेज नहीं है: SQL Server 2012 SP2 डेवलपर संस्करण, 64 बिट, 6 जीबी रैम, दोहरी 2.5 Ghz कोर i5, और एक 5400 RPM SATA ड्राइव। मैं एसएसएमएस 2014, एसक्यूएल सर्वर एक्सप्रेस 2014, क्रोम, और कई अन्य चीजें भी चला रहा हूं।

मेरे सिस्टम के प्रतिक्रिया समय के आधार पर, मैं दोहराऊंगा कि हमें और अधिक जानकारी की आवश्यकता है (यानी तालिका और डेटा के बारे में, सुझाए गए परीक्षणों के परिणाम, आदि) के लिए 20 के कारण को कम करने में मदद करने के लिए - 25 सेकंड का प्रतिक्रिया समय जो आप देख रहे हैं।

SET ANSI_NULLS, NOCOUNT ON;
GO

IF (OBJECT_ID(N'dbo.XmlReadTest') IS NOT NULL)
BEGIN
    PRINT N'Dropping table...';
    DROP TABLE dbo.XmlReadTest;
END;

PRINT N'Creating table...';
CREATE TABLE dbo.XmlReadTest 
(
    ID INT NOT NULL IDENTITY(1, 1),
    Col2 BIGINT,
    Col3 UNIQUEIDENTIFIER,
    Col4 DATETIME,
    Col5 XML,
    CONSTRAINT [PK_XmlReadTest] PRIMARY KEY CLUSTERED ([ID])
);
GO

DECLARE @MaxSets INT = 1000,
        @CurrentSet INT = 1;

WHILE (@CurrentSet <= @MaxSets)
BEGIN
    RAISERROR(N'Populating data (1000 sets of 1000 rows); Set # %d ...',
              10, 1, @CurrentSet) WITH NOWAIT;
    INSERT INTO dbo.XmlReadTest (Col2, Col3, Col4, Col5)
        SELECT  TOP 1000
                CONVERT(BIGINT, CRYPT_GEN_RANDOM(8)),
                NEWID(),
                GETDATE(),
                N'<test>'
                  + REPLICATE(CONVERT(NVARCHAR(MAX), CRYPT_GEN_RANDOM(1), 2), 3750)
                  + N'</test>'
        FROM        [master].[sys].all_columns sac1;

    IF ((@CurrentSet % 100) = 0)
    BEGIN
        RAISERROR(N'Executing CHECKPOINT ...', 10, 1) WITH NOWAIT;
        CHECKPOINT;
    END;

    SET @CurrentSet += 1;
END;

--

SELECT COUNT(*) FROM dbo.XmlReadTest; -- Verify that we have 1 million rows

-- O.P. states that the "clustered index fragmentation is close to 0%"
ALTER INDEX [PK_XmlReadTest] ON dbo.XmlReadTest REBUILD WITH (FILLFACTOR = 90);
CHECKPOINT;

--

DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;

SET STATISTICS IO, TIME ON;
SELECT TOP 1000 * FROM dbo.XmlReadTest;
SET STATISTICS IO, TIME OFF;

/*
Scan count 1, logical reads 21,       physical reads 1,     read-ahead reads 4436,
              lob logical reads 5676, lob physical reads 1, lob read-ahead reads 3967.

 SQL Server Execution Times:
   CPU time = 171 ms,  elapsed time = 8329 ms.
*/

और, क्योंकि हम गैर-एलओबी पृष्ठों को पढ़ने में लगने वाले समय को निकालना चाहते हैं, इसलिए मैंने सभी क्वेरी का चयन करने के लिए निम्न क्वेरी को चलाया लेकिन XML कॉलम (ऊपर दिए गए परीक्षणों में से एक)। यह 1.5 सेकंड में काफी लगातार लौटता है।

DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;

SET STATISTICS IO, TIME ON;
SELECT TOP 1000 ID, Col2, Col3, Col4 FROM dbo.XmlReadTest;
SET STATISTICS IO, TIME OFF;

/*
Scan count 1, logical reads 21,    physical reads 1,     read-ahead reads 4436,
              lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1666 ms.
*/

निष्कर्ष (फिलहाल के लिए)
अपने परिदृश्य को फिर से बनाने के मेरे प्रयास के आधार पर, मुझे नहीं लगता कि हम SATA ड्राइव या गैर-अनुक्रमिक I / O को 20 - 25 सेकंड के मुख्य कारण के रूप में इंगित कर सकते हैं, खासकर क्योंकि हम अभी भी एक्सएमएल कॉलम को शामिल न करने पर क्वेरी कितनी तेजी से लौटती है, यह नहीं जानते। और मैं बड़ी संख्या में पुन: पेश करने तार्किक पढ़ता की (गैर LOB) है कि आप दिखा रहे हैं सक्षम नहीं था, लेकिन मुझे लगता है कि मुझे लगता है कि के आलोक में प्रत्येक पंक्ति के लिए और अधिक डेटा जोड़ने की जरूरत है और के बयान:

~ 90% टेबल पेज LOB_DATA हैं

मेरी तालिका में 1 मिलियन पंक्तियाँ हैं, जिनमें से प्रत्येक में XML डेटा सिर्फ 15k से अधिक है, और sys.dm_db_index_physical_statsदिखाता है कि 2 मिलियन LOB_DATA पृष्ठ हैं। शेष 10% तब 222k IN_ROW डेटा पृष्ठ होंगे, फिर भी मेरे पास केवल 11,630 हैं। इसलिए एक बार फिर, हमें वास्तविक तालिका स्कीमा और वास्तविक डेटा के बारे में अधिक जानकारी की आवश्यकता है।


इस चर्चा को बातचीत में स्थानांतरित कर दिया गया है ।
पॉल व्हाइट GoFundMonica कहते

10

क्या मैं यह सोचने में सही हूं कि LOB_DATA पृष्ठ न केवल उनके आकार के कारण धीमी गति से स्कैन का कारण बन सकते हैं, बल्कि इसलिए भी क्योंकि SQL सर्वर क्लस्टर इंडेक्स को प्रभावी ढंग से स्कैन नहीं कर सकता है

हां, LOB डेटा को इन-रो में संग्रहित नहीं पढ़ने से क्रमिक IO के बजाय यादृच्छिक IO होता है। डिस्क प्रदर्शन मीट्रिक का उपयोग यहां यह समझने के लिए कि यह तेज़ या धीमा क्यों है रैंडम रीड IOPS।

LOB डेटा को ट्री संरचना में संग्रहीत किया जाता है जहां डेटा पेज क्लस्टर इंडेक्स में एक LOB डेटा पेज पर एक LOB रूट संरचना के साथ इंगित करता है जो वास्तविक LOB डेटा को इंगित करता है। जब अनुक्रमणिका SQL सर्वर में रूट नोड को ट्रैवर्स करना केवल अनुक्रमिक रीड्स द्वारा इन-रो डेटा प्राप्त कर सकता है। LOB डेटा प्राप्त करने के लिए SQL सर्वर को डिस्क पर कहीं और जाना पड़ता है।

मुझे लगता है कि यदि आप SSD डिस्क में परिवर्तित हो गए हैं, तो आप इससे ज्यादा पीड़ित नहीं होंगे क्योंकि SSD के लिए यादृच्छिक IOPS एक कताई डिस्क की तुलना में अधिक है।

क्या ऐसी तालिका संरचना / डेटा पैटर्न के लिए उचित माना जाता है?

हाँ यह हो सकता है। इस बात पर निर्भर करता है कि यह तालिका आपके लिए क्या कर रही है।

आमतौर पर SQL सर्वर में XML के साथ प्रदर्शन समस्याएँ तब होती हैं जब आप XML में T-SQL का उपयोग क्वेरी में करना चाहते हैं और इससे भी अधिक जब आप XML से मानों का उपयोग करना चाहते हैं जहां एक खंड या सम्मिलित करें। अगर ऐसा है तो आप प्रॉपर्टी प्रमोशन या सेलेक्टिव XML इंडेक्स या आपकी टेबल स्ट्रक्चर्स के रिडिजाइन पर नज़र डाल सकते हैं, बजाय XML को टेबल पर रखने के।

मैंने कंप्रेशन की कोशिश की

मैंने 10 साल पहले एक बार एक उत्पाद में एक बार किया था और तब से इसे पछतावा है। मैं वास्तव में टी-एसक्यूएल का उपयोग कर डेटा के साथ काम करने में सक्षम नहीं हुआ, इसलिए मैं किसी को भी यह सलाह नहीं दूंगा कि इसे टाला जा सकता है।


उत्तर के लिए बहुत बहुत धन्यवाद। संपीड़न के बारे में: मुझे यकीन नहीं है कि अगर इस तरह की सख्त विरोधी सिफारिश उचित है, क्योंकि टी-एसक्यूएल से डेटा को वास्तव में क्वेरी करने की आवश्यकता संग्रहीत डेटा की प्रकृति पर निर्भर करती है। मेरे मामले में, मैंने अभी के लिए संपीड़न के साथ जाने का फैसला किया।
अलेक्जेंडर शेल्मिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.