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

sys.partitions का प्रदर्शन

sys.partitions एक यूनियन प्रतीत होता है सभी दो परिणाम सेट (पंक्ति स्टोर और कॉलमस्टोर) और मेरे अधिकांश प्रश्नों के परिणामस्वरूप sysrowsets के दो स्कैन होते हैं। क्या कोई फ़िल्टर है जिसे मैं sys.partitions की क्वेरी पर रख सकता हूँ यदि मुझे पता है कि मैं जिस पंक्ति की तलाश कर रहा हूँ वह रोस्टोर है?

यह प्रश्न जेक मैन्सके द्वारा #sqlhelp पर पोस्ट किया गया था, और इसे एरिक डार्लिंग द्वारा मेरे ध्यान में लाया गया था।

मुझे याद नहीं है कि कभी भी sys.partitions . के साथ कोई प्रदर्शन समस्या हुई हो . मेरा प्रारंभिक विचार (जॉय डी'एंटोनी द्वारा प्रतिध्वनित) यह था कि data_compression पर एक फ़िल्टर कॉलम चाहिए अनावश्यक स्कैन से बचें, और क्वेरी रनटाइम को लगभग आधा कर दें। हालाँकि, यह विधेय नीचे धकेला नहीं जाता है, और यही कारण है कि थोड़ा सा अनपैकिंग करता है।

sys.partitions धीमा क्यों है?

यदि आप sys.partitions . की परिभाषा देखें तो , यह मूल रूप से जेक का वर्णन है - एक UNION ALL तीन . के साथ, सभी कॉलमस्टोर और रोस्टोर पार्टिशन में से sys.sysrowsets . के स्पष्ट संदर्भ (संक्षिप्त स्रोत यहां):

CREATE VIEW sys.partitions AS
    WITH partitions_columnstore(...cols...)
    AS
    (
      SELECT ...cols...,
        cmprlevel AS data_compression ...
      	FROM sys.sysrowsets rs OUTER APPLY OpenRowset(TABLE ALUCOUNT, rs.rowsetid, 0, 0, 0) ct
-------- *** ^^^^^^^^^^^^^^ ***
		LEFT JOIN sys.syspalvalues cl ...
		WHERE ... sysconv(bit, rs.status & 0x00010000) = 1 -- Consider only columnstore base indexes
    ),
    partitions_rowstore(...cols...)
    AS
    (
      SELECT ...cols...,
        cmprlevel AS data_compression ...
	FROM sys.sysrowsets rs 
-------- *** ^^^^^^^^^^^^^^ ***
		LEFT JOIN sys.syspalvalues cl ...
		WHERE ... sysconv(bit, rs.status & 0x00010000) = 0 -- Ignore columnstore base indexes and orphaned rows.
    )
    SELECT ...cols...
    from partitions_rowstore p OUTER APPLY OpenRowset(TABLE ALUCOUNT, p.partition_id, 0, 0, p.object_id) ct
    union all
    SELECT ...cols...
    FROM partitions_columnstore as P1
    LEFT JOIN 
      (SELECT ...cols...
       FROM sys.sysrowsets rs OUTER APPLY OpenRowset(TABLE ALUCOUNT, rs.rowsetid, 0, 0, 0) ct
------- *** ^^^^^^^^^^^^^^ ***
      ) ...

यह दृश्य एक साथ उलझा हुआ लगता है, शायद पश्चगामी संगतता चिंताओं के कारण। यह निश्चित रूप से अधिक कुशल होने के लिए फिर से लिखा जा सकता है, विशेष रूप से केवल sys.sysrowsets को संदर्भित करने के लिए और TABLE ALUCOUNT एक बार वस्तुओं। लेकिन अभी आप या मैं इसके बारे में बहुत कुछ नहीं कर सकते।

कॉलम cmprlevel sys.sysrowsets . से आता है (स्तंभ संदर्भ पर एक उपनाम उपसर्ग मददगार होता)। आप उम्मीद करेंगे कि किसी OUTER APPLY से पहले किसी कॉलम के सामने एक विधेय तार्किक रूप से घटित होगा। और एक स्कैन को रोक सकता है, लेकिन ऐसा नहीं होता है। निम्नलिखित सरल क्वेरी चलाना:

SELECT * 
  FROM sys.partitions AS p
  INNER JOIN sys.objects AS o 
  ON p.object_id = o.object_id
  WHERE o.is_ms_shipped = 0;

डेटाबेस में कॉलमस्टोर इंडेक्स होने पर निम्न योजना प्राप्त होती है (विस्तार करने के लिए क्लिक करें):

sys.partitions के लिए योजना, जिसमें कॉलमस्टोर इंडेक्स मौजूद हैं

और निम्न योजना जब नहीं हैं (विस्तार करने के लिए क्लिक करें):

sys.partitions के लिए योजना, जिसमें कोई कॉलमस्टोर इंडेक्स मौजूद नहीं है

ये वही अनुमानित योजना हैं, लेकिन जब किसी ऑपरेशन को रनटाइम पर छोड़ दिया जाता है तो सेंट्रीऑन प्लान एक्सप्लोरर हाइलाइट करने में सक्षम होता है। यह बाद के मामले में तीसरे स्कैन के लिए होता है, लेकिन मुझे नहीं पता कि रनटाइम स्कैन गिनती को और कम करने का कोई तरीका है; दूसरा स्कैन तब भी होता है जब क्वेरी शून्य पंक्तियाँ लौटाती है।

जेक के मामले में, उसके पास बहुत कुछ . है वस्तुओं की, इसलिए इस स्कैन को दो बार भी करना ध्यान देने योग्य, दर्दनाक और एक बार बहुत अधिक है। और ईमानदारी से मुझे नहीं पता कि TABLE ALUCOUNT , एक आंतरिक और गैर-दस्तावेज लूपबैक कॉल, को इनमें से कुछ बड़ी वस्तुओं को कई बार स्कैन करना पड़ता है।

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

क्या कोई अन्य दृश्य काम करेगा?

हालाँकि, हम पूरी तरह से एक अलग दृष्टिकोण की कोशिश कर सकते हैं। मैंने अन्य विचारों की तलाश की जिनमें sys.sysrowsets . दोनों के संदर्भ शामिल थे और ALUCOUNT , और कई हैं जो सूची में दिखाई देते हैं, लेकिन केवल दो आशाजनक हैं:sys.internal_partitions और sys.system_internals_partitions .

sys.internal_partitions

मैंने कोशिश की sys.internal_partitions पहला:

SELECT *
  FROM sys.internal_partitions AS p
  INNER JOIN sys.objects AS o 
  ON p.object_id = o.object_id
  WHERE o.is_ms_shipped = 0;

लेकिन योजना ज्यादा बेहतर नहीं थी (विस्तार करने के लिए क्लिक करें):

sys.internal_partitions के लिए योजना

sys.sysrowsets . के विरुद्ध केवल दो स्कैन हैं इस बार, लेकिन स्कैन वैसे भी अप्रासंगिक हैं क्योंकि क्वेरी उन पंक्तियों को बनाने के करीब नहीं आती है जिनमें हम रुचि रखते हैं। हम केवल कॉलमस्टोर से संबंधित वस्तुओं के लिए पंक्तियाँ देखते हैं (जैसा कि दस्तावेज़ीकरण बताता है)।

sys.system_internals_partitions

आइए कोशिश करते हैं sys.system_internals_partitions . मैं इसके बारे में थोड़ा सावधान हूं, क्योंकि यह असमर्थित है (यहां चेतावनी देखें), लेकिन एक क्षण मेरे साथ रहें:

SELECT *
  FROM sys.system_internals_partitions AS p
  INNER JOIN sys.objects AS o 
  ON p.object_id = o.object_id
  WHERE o.is_ms_shipped = 0;

कॉलमस्टोर इंडेक्स वाले डेटाबेस में, sys.sysschobjs के खिलाफ एक स्कैन होता है , लेकिन अब केवल एक sys.sysrowsets . के विरुद्ध स्कैन करें (विस्तार करने के लिए क्लिक करें):

sys.system_internals_partitions के लिए योजना, जिसमें कॉलमस्टोर इंडेक्स मौजूद हैं

यदि हम डेटाबेस में एक ही क्वेरी को बिना किसी कॉलमस्टोर इंडेक्स के चलाते हैं, तो योजना और भी सरल है, जिसमें sys.sysschobjs की तलाश है। (विस्तार करने के लिए क्लिक करें):

sys.system_internals_partitions के लिए योजना, जिसमें कोई कॉलमस्टोर इंडेक्स मौजूद नहीं है

हालांकि, यह काफी नहीं है हम क्या कर रहे हैं, या कम से कम जेक के बाद क्या नहीं था, क्योंकि इसमें कॉलमस्टोर इंडेक्स से कलाकृतियों को भी शामिल किया गया है। यदि हम इन फ़िल्टरों को जोड़ते हैं, तो वास्तविक आउटपुट अब हमारी पहले की, अधिक महंगी क्वेरी से मेल खाता है:

SELECT *
  FROM sys.system_internals_partitions AS p
  INNER JOIN sys.objects AS o ON p.object_id = o.object_id
  WHERE o.is_ms_shipped = 0
    AND p.is_columnstore = 0
    AND p.is_orphaned = 0;

एक बोनस के रूप में, sys.sysschobjs . के विरुद्ध स्कैन करें कॉलमस्टोर ऑब्जेक्ट्स वाले डेटाबेस में भी एक तलाश बन गई है। हममें से अधिकांश लोग उस अंतर पर ध्यान नहीं देंगे, लेकिन यदि आप जेक जैसे परिदृश्य में हैं, तो आप शायद (विस्तार करने के लिए क्लिक करें):

sys.system_internals_partitions के लिए अतिरिक्त फ़िल्टर के साथ सरल योजना

sys.system_internals_partitions sys.partitions . की तुलना में स्तंभों के भिन्न सेट को प्रदर्शित करता है (कुछ पूरी तरह से अलग हैं, अन्य के नए नाम हैं) इसलिए, यदि आप डाउनस्ट्रीम आउटपुट का उपभोग कर रहे हैं, तो आपको उनके लिए समायोजित करना होगा। आप यह भी सत्यापित करना चाहेंगे कि यह रोस्टोर, मेमोरी-ऑप्टिमाइज़्ड और कॉलमस्टोर इंडेक्स में आपकी इच्छित सभी जानकारी लौटाता है, और उन अजीब ढेर के बारे में मत भूलना। और, अंत में, s . को छोड़ने के लिए तैयार रहें internals . में कई, कई बार।

निष्कर्ष

जैसा कि मैंने ऊपर उल्लेख किया है, यह सिस्टम दृश्य आधिकारिक रूप से समर्थित नहीं है, इसलिए इसकी कार्यक्षमता किसी भी समय बदल सकती है; इसे डेडिकेटेड एडमिनिस्ट्रेटर कनेक्शन (DAC) के तहत भी स्थानांतरित किया जा सकता है, या उत्पाद से पूरी तरह से हटाया जा सकता है। इस दृष्टिकोण का उपयोग करने के लिए स्वतंत्र महसूस करें यदि sys.partitions आपके लिए अच्छा काम नहीं कर रहा है, लेकिन कृपया सुनिश्चित करें कि आपके पास एक बैकअप योजना है। और सुनिश्चित करें कि जब आप SQL सर्वर के भविष्य के संस्करणों का परीक्षण शुरू करते हैं, या अपग्रेड करने के बाद, बस मामले में इसे आपके द्वारा प्रतिगमन परीक्षण के रूप में प्रलेखित किया जाता है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. स्नैपशॉट प्रतिकृति कैसे बनाएं

  2. ऑप्टिमाइज़ेशन थ्रेशोल्ड - डेटा को समूहीकृत और एकत्र करना, भाग 2

  3. शिक्षा के लिए एक खुले बाजार की मॉडलिंग

  4. SQLCMD का उपयोग करके SQL डेटाबेस रखरखाव कार्य चलाना

  5. शत शत! डेटा मॉडल में पुनरावर्ती ईवेंट प्रबंधित करना