2010-02-08 6 views
17

में गणना (*) बनाम गणना (आईडी) मैं तालिका से कुल संख्या या पंक्ति प्राप्त करने के लिए SQL COUNT फ़ंक्शन का उपयोग करता हूं। क्या निम्नलिखित दो कथनों के बीच कोई अंतर है?एसक्यूएल सर्वर 2005

SELECT COUNT(*) FROM Table 

और

SELECT COUNT(TableId) FROM Table 
इसके अलावा

, वहाँ प्रदर्शन और निष्पादन समय के संदर्भ में कोई अंतर है?

+0

पहले से ही उत्तर दिया, लेकिन इस बारे में यहाँ बहुत अच्छी चर्चा: http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/31795984-ea62-4b2c-8c78-6e986f2bcea0 –

उत्तर

18

थिलो अंतर किसी न किसी ठीक ... COUNT(column_name) से COUNT(*) अगर column_nameNULL हो सकता है एक कम संख्या लौट सकते हैं।

हालांकि, अगर मैं आपके प्रश्न का उत्तर देने के लिए थोड़ा अलग कोण ले सकता हूं, क्योंकि आप प्रदर्शन पर ध्यान केंद्रित कर रहे हैं।

सबसे पहले, ध्यान दें कि SELECT COUNT(*) FROM table; जारी करने के संभावित लेखकों को अवरुद्ध कर देगा, और यह भी अन्य पाठकों/लेखकों द्वारा अवरुद्ध हो जाएगा जब तक आप अलगाव के स्तर को बदल दिया (घुटने झटका WITH (NOLOCK) हो जाता है, लेकिन मैं का एक होनहार संख्या दिखाई दे रही है लोग अंततः आरसीएसआई में विश्वास करना शुरू कर देते हैं)। जिसका अर्थ यह है कि जब आप अपनी "सटीक" गिनती प्राप्त करने के लिए डेटा पढ़ रहे हैं, तो ये सभी डीएमएल अनुरोध पिलिंग हो रहे हैं, और जब आपने आखिरकार अपने सभी ताले जारी किए हैं, बाढ़ के खुले हैं, डालने/अपडेट/हटाए जाने का एक गुच्छा गतिविधि होती है, और आपकी "सटीक" गणना होती है।

यदि आपको पूरी तरह से संगत और सटीक पंक्ति गणना की आवश्यकता है (भले ही यह केवल मिलीसेकंड की संख्या के लिए मान्य है, तो यह आपको संख्या वापस करने के लिए लेता है), तो SELECT COUNT(*) आपकी एकमात्र पसंद है।

दूसरी ओर, यदि आप एक 99.9% सही बॉलपार्क पाने के लिए कोशिश कर रहे हैं, तो आप ज्यादा इस तरह एक प्रश्न के साथ बेहतर कर रहे हैं:

SELECT row_count = SUM(row_count) 
    FROM sys.dm_db_partition_stats 
    WHERE [object_id] = OBJECT_ID('dbo.Table') 
    AND index_id IN (0,1); 

(SUM है विभाजित तालिकाओं के लिए खाते - यदि आप टेबल विभाजन का उपयोग नहीं कर रहे हैं, तो आप इसे छोड़ सकते हैं।)

यह डीएमवी वर्तमान में लेन-देन में भाग लेने वाली पंक्तियों के अपवाद के साथ सटीक पंक्ति गणना बनाए रखता है - और वे लेनदेन वे हैं जो अपना SELECT COUNT क्वेरी प्रतीक्षा करें (और अंत में इसे पढ़ने के लिए समय होने से पहले इसे गलत बना दें)। लेकिन अन्यथा यह आपके द्वारा प्रस्तावित क्वेरी की तुलना में बहुत तेज़ उत्तर देगा, और WITH (NOLOCK) का उपयोग करने से कम सटीक नहीं होगा।

+0

की गणना होती है (Primary_Key) ऊपर की क्वेरी से बेहतर विकल्प होगा? इसे हमेशा सटीक गिनती देना चाहिए क्योंकि शून्य मानों के साथ प्राथमिक कुंजी नहीं हो सकती है। –

+2

COUNT (पीके) और COUNT (*) उस मामले में समान होंगे। प्रत्येक एक सटीक गिनती देगा, लेकिन अभी भी एक अवरोधक हो सकता है और अभी भी अवरुद्ध हो सकता है। तो क्या वह संभावित प्रदर्शन हत्यारा सटीकता के लायक है आपके ऊपर है (ध्यान रखें कि यदि आप NOLOCK का उपयोग करके समस्या को हल करते हैं, तो आपने अपनी सटीकता खो दी है)। –

+0

मैं हमेशा गणना करने के लिए उपयोग करता हूं गणना (पीके) गणना (*) से बेहतर प्रदर्शन करता है। इसे साफ़ करने के लिए धन्यवाद। –

12

गिनती (आईडी) को कॉलम को शून्य-जांचने की आवश्यकता है (जिसे प्राथमिक कुंजी या अन्यथा नल कॉलम के लिए अनुकूलित किया जा सकता है), इसलिए गिनती (*) या गिनती (1) को प्राथमिकता दी जानी चाहिए (जब तक आप वास्तव में नहीं आईडी के लिए गैर-शून्य मूल्य वाले पंक्तियों की संख्या जानना चाहते हैं)।