2012-06-21 13 views
25

मेरे पास 20 लाख से अधिक पंक्तियों के साथ एक SQL तालिका BookChapters है। इसमें क्लस्टर्ड प्राथमिक कुंजी (bookChapterID) है और इसमें कोई अन्य कुंजी या अनुक्रमणिका नहीं है। यह निम्न क्वेरी चलाने के लिएएसक्यूएल गिनती (*) प्रदर्शन

if (select count(*) from BookChapters) = 0 
... 

हालांकि मिलीसेकंड लेता है, जब मैं इसे पसंद तो

if (select count(*) from BookChapters) = 1 
... 

या

if (select count(*) from BookChapters) > 1 
... 

क्यों कि है बदल यह 10 मिनट से अधिक लेता है? तेजी से निष्पादित करने के लिए मुझे select count(*) कैसे मिल सकता है?

+2

आम तौर पर चयन बोल " तालिका से गिनती (*) "- बड़े डेटा के साथ बड़ी समस्याएं हो सकती हैं;) –

उत्तर

40

माइकल एरिकसन bellow क्यों पहली क्वेरी तेज है एक अच्छा व्याख्या है। तो यह तालिका में सभी पंक्तियों की गणना करने के बजाय एक पंक्ति की उपस्थिति की तलाश में जाता है।

अन्य दो प्रश्नों के लिए, SQL सर्वर निम्न नियम का उपयोग करेगा। SELECT COUNT(*) जैसी क्वेरी करने के लिए, SQL सर्वर पंक्तियों की गणना करने के लिए संकीर्ण गैर-क्लस्टर अनुक्रमणिका का उपयोग करेगा। यदि तालिका में गैर-क्लस्टर इंडेक्स नहीं है, तो उसे तालिका को स्कैन करना होगा।

इसके अलावा, आप निम्न क्वेरी (इस साइट Get Row Counts Fast! से उधार)

--SQL Server 2005/2008 
SELECT OBJECT_NAME(i.id) [Table_Name], i.rowcnt [Row_Count] 
FROM sys.sysindexes i WITH (NOLOCK) 
WHERE i.indid in (0,1) 
ORDER BY i.rowcnt desc 

--SQL Server 2000 
SELECT OBJECT_NAME(i.id) [Table_Name], i.rows [Row_Count] 
FROM sysindexes i (NOLOCK) 
WHERE i.indid in (0,1) 
ORDER BY i.rows desc 

यह sysindexes प्रणाली तालिका का उपयोग करता का उपयोग कर भी तेजी से अपनी गिनती प्राप्त कर सकते हैं अपनी मेज एक क्लस्टर सूचकांक है। अधिक जानकारी आप यहाँ पा सकते हैं SQL Server 2000, SQL Server 2005, SQL Server 2008, SQL Server 2012

यहाँ एक और समाधान के साथ एक और लिंक Why is my SELECT COUNT(*) running so slow? है। यह तकनीक दिखाता है कि जब आप तालिका पर राइट क्लिक करते हैं और गुणों का चयन करते हैं तो माइक्रोसॉफ्ट पंक्तियों की संख्या को त्वरित रूप से प्रदर्शित करने के लिए उपयोग करता है।

select sum (spart.rows) 
from sys.partitions spart 
where spart.object_id = object_id(’YourTable’) 
and spart.index_id < 2 

आपको यह पता होना चाहिए कि यह कितनी जल्दी है, इससे कोई फर्क नहीं पड़ता कि आपके पास कितनी टेबल हैं।

यदि आप SQL 2000 का उपयोग कर रहे हैं तो भी आप संख्या प्राप्त करने के लिए sysindexes तालिका का उपयोग कर सकते हैं।

select max(ROWS) 
from sysindexes 
where id = object_id(’YourTable’) 

यह संख्या थोड़ा कितनी बार एसक्यूएल अद्यतन करता sysindexes तालिका के आधार पर बंद किया जा सकता है, लेकिन यह आमतौर corrent (या कम से कम इतने पास) है।

+1

क्या आप मेरे सुझाव से सहमत हैं? –

+1

हाय Aleksey, आप प्रतिभाशाली हैं, यह है कि, मैं सिर्फ उत्सुक था कि मेरी नई तालिका BookChapters2 क्वेरी गिनती को बहुत तेजी से वापस कर देता है, मैंने देखा, जैसा कि आपने कहा था, क्योंकि तालिका के अंदर एक गैर-क्लस्टर इंडेक्स है, धन्यवाद महान उत्तर के लिए – danmiao

+1

+1 - धन्यवाद! बस एक अतिरिक्त बिंदु। सुनिश्चित करें कि पूछताछ की जा रही तालिका में इंडेक्स/आंकड़े अद्यतित हैं। चूंकि यह गिनती के लिए उन आंकड़ों का उपयोग करता है, इसलिए पुराने आंकड़े गलत परिणाम देंगे। – jabs

4

क्या आपने select count(BookChapterId) from BookChapterTable पर विचार किया था? - जहां 'BookChapterId गैर-क्लस्टर सूचकांक है। इससे इसे बहुत तेजी से चलाना चाहिए।

कैसे तालिका प्रयोग किया जाता है और पंक्तियाँ, पहुँचा nonclustered अनुक्रमणिका के खिलाफ की क्वेरी प्रमुख मुद्दा हो सकता है पर निर्भर करता है: मैं बस कुछ बिंदुओं MDSN से ले लिया:

  • इससे पहले कि आप nonclustered अनुक्रमणिका बनाने के लिए, कैसे अपने डेटा को समझने का उपयोग किया जाएगा। गैर-बस्टर्ड इंडेक्स का उपयोग करने पर विचार करें:
  • कॉलम जिनमें
    अंतिम नाम और पहला नाम संयोजन (यदि क्लस्टरर्ड इंडेक्स अन्य कॉलम के लिए उपयोग किया जाता है) के कॉलम जिनमें बड़ी संख्या में विशिष्ट मान होते हैं। यदि
    केवल 1 और 0 जैसे बहुत कम विशिष्ट मान हैं, तो अधिकांश प्रश्न इंडेक्स का उपयोग नहीं करेंगे क्योंकि तालिका
    स्कैन आमतौर पर अधिक कुशल होती है।
  • क्वेरी जो बड़े परिणाम सेट नहीं लौटती हैं।
  • कॉलम अक्सर एक क्वेरी की खोज स्थितियों में शामिल होते हैं (WHERE
    खंड) जो सटीक मिलान वापस करता है।
  • निर्णय-समर्थन-सिस्टम अनुप्रयोग जो जुड़ने और समूह करने के लिए अक्सर आवश्यक हैं। कॉलम पर एकाधिक गैर-क्लस्टर इंडेक्स बनाएं, जो समूह में शामिल होने और समूहबद्ध संचालन में शामिल हैं, और पर किसी भी क्लस्टर इंडेक्स को किसी भी विदेशी कुंजी कॉलम पर शामिल करें।
  • किसी दिए गए प्रश्न में एक तालिका से सभी कॉलम को कवर करना। यह तालिका या क्लस्टर्ड इंडेक्स को पूरी तरह से एक्सेस करता है। if exists(select * from BookChapters):

    एसक्यूएल सर्वर में यह अनुकूलन:

+0

हाय ईयूयूसुबोव, मैंने परीक्षण किया, कोई फर्क नहीं पड़ता, अभी भी बहुत धीमा है – danmiao

+0

कृपया अपनी अनुक्रमणिका पर फिर से जाएं, हो सकता है कि आपके पास समग्र इंडेक्स हो, या आपको उन्हें पुनर्निर्माण करने की आवश्यकता है । –

+0

हाय EIYusubov, यह एक एकल कॉलम क्लस्टर इंडेक्स है, समग्र इंडेक्स नहीं, मैंने प्राथमिक कुंजी को हटा दिया है और इसे फिर से बनाया है, लेकिन कोई फर्क नहीं पड़ता। – danmiao

7

यदि आप अपने प्रश्नों के लिए निष्पादन योजनाओं पर नज़र डालते हैं तो आप देखेंगे कि क्या हो रहा है।

आपकी पहली क्वेरी if (select count(*) from BookChapters) = 0 क्वेरी ऑप्टिमाइज़र द्वारा if exists(select * from BookChapters) के रूप में पहचानी जाती है। एसक्यूएल सर्वर जानता है कि अगर अभिव्यक्ति कम से कम एक पंक्ति मौजूद है तो अभिव्यक्ति सच है, इसलिए यह तालिका में सभी पंक्तियों की गणना करने के बजाय एक पंक्ति की उपस्थिति की तलाश में है।

अपने अन्य प्रश्नों के लिए यह स्मार्ट नहीं हो सकता है और यह तय करने से पहले तालिका में पंक्तियों की संख्या को गिनना होगा कि अभिव्यक्ति सही या गलत का मूल्यांकन करती है या नहीं।

3

इस कोशिश, अगर आप पता लगाने के लिए, अगर तालिका एक से अधिक पंक्तियां हैं की जरूरत है:

if (SELECT COUNT(*) FROM (SELECT TOP 2 * FROM BookChapters) AS b) > 1 
11

यह कोशिश अगर आप केवल पता करने के लिए पंक्तियों गिनती हैं:

exec sp_spaceused [TABLE_NAME] 
संबंधित मुद्दे