sql-server - SQL सर्वर में COUNT(*)एक निरंतर समय ऑपरेशन है? यदि नहीं, तो क्यों नहीं?




(3)

हमें पूरी पंक्तियों को "लोड" करने की आवश्यकता क्यों है

हम नहीं करते। SQL सर्वर सबसे छोटे इंडेक्स का उपयोग करेगा जो कि क्वेरी को संतुष्ट कर सकता है।

Count(*) (बिना किसी फ़िल्टरिंग) इस तरह के एक आम ऑपरेशन है

मुझे लगता है कि आप इसकी व्यापकता का अनुमान लगाते हैं। मुझे याद नहीं है कि पिछली बार मैंने एक ही तालिका में कुल पंक्तियों की कुल संख्या के बारे में अधिक फ़िल्टर किए गए दृश्य या अधिक जटिल ऑपरेशन में शामिल की गई गिनती को याद किया था।

यह एक असाधारण संकीर्ण अनुकूलन होगा जो केवल क्वेरी की एकल शैली को लाभान्वित कर सकता है, और जैसा कि मैं कहता हूं, मुझे लगता है कि आपने कितनी बार ऐसा किया है।

मैं इस चर्चा को एक अन्य पोस्ट में पढ़ रहा था जहां यह प्रश्न किसी और ने उठाया था। चर्चा को पढ़ने से पहले, मैंने हमेशा सोचा था कि SQL सर्वर (और अन्य DBMS) मेटाडेटा में कहीं न कहीं प्रत्येक तालिका के लिए पंक्तियों की एक वैश्विक गणना रखता है, लेकिन चर्चा यह कहती है कि ऐसा नहीं है। क्यूं कर? Count(*) (किसी भी फ़िल्टरिंग के बिना) इस तरह के एक सामान्य ऑपरेशन होने पर ओ (1) होने पर भारी वृद्धि मिलेगी। यहां तक ​​कि COUNT(*) पर विचार नहीं करते हुए, तालिका में पंक्तियों की कुल संख्या ऐसी मूलभूत जानकारी है। वे इसका ध्यान क्यों नहीं रखते हैं?

इसके अलावा, हमें पूरी पंक्तियों को "लोड" करने की आवश्यकता क्यों है (जैसा कि मैंने पोस्ट किए गए पोस्ट में संकेत दिया है) बस उन्हें गिनने के लिए? क्या अनुक्रमणिका या पीके आदि को गिनने के लिए पर्याप्त नहीं होना चाहिए?


नहीं, COUNT(*) एक निरंतर समय ऑपरेशन नहीं है। एक COUNT(*) पंक्तियों की एक गिनती लौटा देनी चाहिए जो वर्तमान स्कैन के अनुरूप होती है (यानी। WHERE क्लॉज़), ताकि अकेले ही मेटाडेटा की संपत्ति की वापसी अमान्य हो जाए। लेकिन यहां तक ​​कि अगर आपके पास कोई विधेय नहीं है, तो भी COUNT को वर्तमान लेनदेन अलगाव शब्दार्थ, यानी संतुष्ट करना होगा। दिखाई देने वाली पंक्तियों की गिनती लौटाएं (उदाहरण के लिए। प्रतिबद्ध)। इसलिए COUNT , और SQL सर्वर में, वास्तव में स्कैन और पंक्तियों की गणना करेगा। कुछ सिस्टम तेज 'अनुमान' की गिनती की वापसी की अनुमति देते हैं।

इसके अलावा, एक पक्ष की टिप्पणी के रूप में, docs.microsoft.com/en-us/sql/relational-databases/… में rows पर निर्भर अविश्वसनीय है। आखिरकार, अगर यह गणना सटीक होगी, तो हमें DBCC UPDATEUSAGE(...) WITH COUNT_ROWS आवश्यकता नहीं होगी। ऐसे कई परिदृश्य हैं जो ऐतिहासिक रूप से इस काउंटर को वास्तविकता से अलग करने का कारण बनेंगे (ज्यादातर न्यूनतम लॉग इन रोलबैक), मुझे पता है कि सभी निश्चित हैं, लेकिन यह अभी भी 1 की समस्याओं को छोड़ देता है) पहले के संस्करणों से उन्नत तालिकाओं में बग और 2 थे ) अन्य, अभी तक नहीं खोजा, कीड़े।

इसके अलावा, हमें पूरी पंक्तियों को "लोड" करने की आवश्यकता क्यों है (जैसा कि मैंने पोस्ट किए गए पोस्ट में संकेत दिया है) बस उन्हें गिनने के लिए? क्या अनुक्रमणिका या पीके आदि को गिनने के लिए पर्याप्त नहीं होना चाहिए?

यह 100% सच नहीं है। कम से कम 2 परिदृश्य हैं जो 'संपूर्ण पंक्तियों को लोड नहीं' करते हैं:

  • संकरी रोवरस्टोर इंडेक्स केवल 'इंडेक्स' पंक्ति को लोड करते हैं, जो बहुत छोटा हो सकता है
  • कॉलमस्टोर डेटा प्रासंगिक कॉलम सेगमेंट को लोड करता है

और जो मैं ऊपर कहता हूं, उनमें से अधिकांश हेकोटन तालिकाओं के लिए लागू नहीं होते हैं।


इस तरह के प्रश्नों के लिए INFORMATION_SCHEMA व्यू का उपयोग करना हमेशा सर्वोत्तम होता है। ये विचार कई अलग-अलग डेटाबेस में (अधिकतर) मानक हैं और शायद ही कभी संस्करण से संस्करण में बदल जाते हैं।

यह जांचने के लिए कि कोई तालिका मौजूद है या नहीं:

IF (EXISTS (SELECT * 
                 FROM INFORMATION_SCHEMA.TABLES 
                 WHERE TABLE_SCHEMA = 'TheSchema' 
                 AND  TABLE_NAME = 'TheTable'))
BEGIN
    --Do Stuff
END




sql sql-server count