2012-09-18 11 views
28

बड़ी मात्रा में डेटा के साथ तालिकाओं की गणना बहुत धीमी हो सकती है, कभी-कभी इसमें कुछ मिनट लगते हैं; यह एक व्यस्त सर्वर पर डेडलॉक भी उत्पन्न कर सकता है। मैं वास्तविक मूल्य प्रदर्शित करना चाहता हूं, NOLOCK एक विकल्प नहीं है।SQL सर्वर गणना धीमी है

मेरे द्वारा उपयोग किए जाने वाले सर्वर SQL Server 2005 या 2008 मानक या एंटरप्राइज़ हैं - यदि यह महत्वपूर्ण है। मैं कल्पना कर सकता हूं कि SQL सर्वर प्रत्येक तालिका के लिए गणना बनाए रखता है और यदि कोई WHERE क्लॉज नहीं है तो मैं उस नंबर को बहुत तेज़ी से प्राप्त कर सकता हूं, है ना?

उदाहरण के लिए:

SELECT COUNT(*) FROM myTable 

तुरंत सही मान के साथ वापस आ जाएगी। क्या मुझे अद्यतन होने के आंकड़ों पर भरोसा करने की ज़रूरत है?

+2

एक [क्वेरी निष्पादन योजना] जाओ (http://stackoverflow.com/questions/7359702/how-do -आई-प्राप्त-ए-क्वेरी-निष्पादन-योजना), तो हम बात कर सकते हैं ...(आंकड़े का उपयोग करने के बजाय 'SELECT COUNT' तालिका से सीधे पूछताछ करता है, क्योंकि आंकड़े पुराने हो सकते हैं) – Justin

+2

बेवकूफ सवाल, लेकिन क्या आपके पास एक अनुक्रमणिका है? – Kermit

+0

@FreshPrinceOfSO यदि आप 'आईडी' (बिगिन, प्राथमिक कुंजी, पहचान विनिर्देश = सत्य) पर भरोसा करते हैं तो यह अभी भी धीमा है। – ANeves

उत्तर

37

बहुत पास अनुमानित (किसी भी उड़ान में लेन-देन की अनदेखी) होगा:

SELECT SUM(p.rows) FROM sys.partitions AS p 
    INNER JOIN sys.tables AS t 
    ON p.[object_id] = t.[object_id] 
    INNER JOIN sys.schemas AS s 
    ON s.[schema_id] = t.[schema_id] 
    WHERE t.name = N'myTable' 
    AND s.name = N'dbo' 
    AND p.index_id IN (0,1); 

हो जाएगा ताकि COUNT (*) से बहुत अधिक तेज़ी से लौटें, और यदि आपकी तालिका जल्दी से बदल रही है, तो यह वास्तव में कम सटीक नहीं है - अगर आपने अपनी COUNT शुरू की और जब इसे वापस किया गया था, तो आपकी तालिका बदल गई है, क्या यह अधिक मूल्यवान है ?

+0

इसका उपयोग तब भी किया जा सकता है जब कोई अनुक्रमणिका मौजूद न हो। – Kermit

+0

आपका समाधान बहुत ही आशाजनक लग रहा था लेकिन लगभग 5 मिलियन रिकॉर्ड पर परीक्षण करने के बाद, मुझे वही प्रतिक्रिया समय मिला। जल्द ही बड़े डेटाबेस पर परीक्षण करेंगे। – Adi

+2

@Adi sys.partitions के खिलाफ एक प्रश्न एक लंबा समय लगा? मुझे लगा कि विश्वास करना बहुत मुश्किल है। –

8

-

(कैसे बड़े "डेटा की बड़ी राशि" क्या है? यह पहली टिप्पणी की जाना चाहिए था, लेकिन शायद नीचे कार्यकारी आप पहले से ही बाहर में मदद करता है) अगर मैं एक स्थिर पर कोई क्वेरी चलाए (जिसका अर्थ और कोई नहीं है थोड़ी देर में पढ़ने/लिखने/अपडेट के साथ परेशान करना, इसलिए विवाद कोई समस्या नहीं है) मेरी देव मशीन (ऑरैकल) पर 15 सेकंड में 200 मिलियन पंक्तियों और COUNT (*) के साथ तालिका। डेटा की शुद्ध राशि को देखते हुए, यह अभी भी काफी तेजी से (कम से कम मेरे लिए)

जैसा कि आपने कहा NOLOCK एक विकल्प नहीं है, तो आप

exec sp_spaceused 'myTable' 

रूप में अच्छी तरह विचार कर सकते है।

लेकिन इस पिन नीचे लगभग करने के लिए NOLOCK के रूप में ही (विवाद अनदेखी +/अद्यतन afaik हटाना)

2

गणना या तो तालिका स्कैन या इंडेक्स स्कैन करेगा। तो पंक्तियों की एक बड़ी संख्या के लिए यह धीमा हो जाएगा। यदि आप अक्सर यह ऑपरेशन करते हैं, तो सबसे अच्छा तरीका गिनती रिकॉर्ड को किसी अन्य तालिका में रखना है।

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

select 
    row_count 
from sys.dm_db_partition_stats as p 
inner join sys.indexes as i 
    on p.index_id = i.index_id 
    and p.object_id = i.object_id 
where i.name = 'your index' 

मैं सुझाव दे रहा हूँ एक नई अनुक्रमणिका बनाना, क्योंकि यह एक (यदि इसका उपयोग नहीं किया जाएगा) अन्य परिचालनों के दौरान बंद नहीं होगा।

जैसा कि हारून बर्ट्रैंड ने कहा था, क्वेरी को बनाए रखना अधिक महंगा हो सकता है, फिर पहले से मौजूद एक का उपयोग कर। तो पसंद तुम्हारा है।

+0

लेकिन अगर यह सूचकांक अन्य * पढ़ने * संचालन के लिए उपयोग नहीं किया जाता है, फिर भी इसे अन्य डीएमएल के लिए बनाए रखा जाना है। मुझे लगता है कि यह डमी इंडेक्स आपके विचार से महंगा है। –

+0

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

0

यदि आपको केवल पंक्तियों की संख्या की किसी न किसी गिनती की आवश्यकता है, यानी। निम्न कार्य, यकीन है कि एक तालिका सही ढंग से लोड करने के लिए या सुनिश्चित करें कि डेटा को नहीं हटाया गया बनाने के लिए:

MySQL> connect information_schema; 
MySQL> select table_name,table_rows from tables;