2011-06-21 21 views
7

मेरे पास एक प्रश्न है;धीमी एसक्यूएल प्रदर्शन

SELECT COUNT(Id) FROM Table 

तालिका में 33 मिलियन रिकॉर्ड हैं - इसमें आईडी पर कोई प्राथमिक कुंजी नहीं है और कोई अन्य सूचकांक नहीं है।

क्वेरी में 30 सेकंड लगते हैं।

वास्तविक निष्पादन योजना से पता चलता है कि यह क्लस्टर्ड इंडेक्स स्कैन का उपयोग करता है।

हमने तालिका का विश्लेषण किया है और पाया है कि यह इस लिंक में दिखाए गए पहले प्रश्न का उपयोग करके खंडित नहीं है: http://sqlserverpedia.com/wiki/Index_Maintenance

कोई भी विचार क्यों है कि यह क्वेरी इतनी धीमी है और इसे कैसे ठीक किया जाए।

तालिका परिभाषा:

CREATE TABLE [dbo].[DbConversation](
[ConversationID] [int] IDENTITY(1,1) NOT NULL, 
[ConversationGroupID] [int] NOT NULL, 
[InsideIP] [uniqueidentifier] NOT NULL, 
[OutsideIP] [uniqueidentifier] NOT NULL, 
[ServerPort] [int] NOT NULL, 
[BytesOutbound] [bigint] NOT NULL, 
[BytesInbound] [bigint] NOT NULL, 
[ServerOutside] [bit] NOT NULL, 
[LastFlowTime] [datetime] NOT NULL, 
[LastClientPort] [int] NOT NULL, 
[Protocol] [tinyint] NOT NULL, 
[TypeOfService] [tinyint] NOT NULL, 
    CONSTRAINT [PK_Conversation_1] PRIMARY KEY CLUSTERED 
(
[ConversationID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

एक बात मैं देखा है डेटाबेस 1 एमबी मात्रा में विकसित करने के लिए सेट कर दिया जाता है।

यह एक लाइव सिस्टम है, इसलिए हम किसी भी विचार के साथ क्या खेल सकते हैं में प्रतिबंधित है?

अद्यतन:

ठीक है - हम उचित कॉलम पर नए गैर क्लस्टर सूचकांक जोड़ने तो यह एक महत्वपूर्ण मुद्दा नहीं रह गया है द्वारा ब्याज की वास्तविक क्वेरी में प्रदर्शन में सुधार किया है।

SELECT COUNT अभी भी धीमा है - इसे NOLOCK संकेतों के साथ प्रयास किया - कोई अंतर नहीं।

हम सभी सोच रहे हैं कि यह ऑटोग्राउथ सेट के साथ एक बड़ी संख्या के बजाय 1 एमबी पर सेट करने के लिए कुछ है, लेकिन हैरान है कि इसका प्रभाव है। डिस्क पर एमडीएफ विखंडन संभव कारण हो सकता है?

+1

प्रश्न 1: क्या आपको वास्तव में सटीक गिनती की आवश्यकता है? या सिर्फ एक अनुमान? –

+0

न तो - यह केवल एक प्रश्न है जिसे हम किसी और चीज़ पर धीमी प्रदर्शन को देखने के बाद दौड़ते हैं। हम यह जानकर आश्चर्यचकित हुए कि यह बहुत धीमी थी। आंकड़े अपडेट करने का प्रयास करेंगे, लेकिन वे स्वत: अद्यतन करने के लिए सेट हैं। – BonyT

+0

क्या आप बस स्थिरता का उपयोग नहीं कर सकते? मेरा मतलब है, इसमें 33 मिलियन ~ या वास्तव में 33.212.2 9 3 रिकॉर्ड होने के बीच का अंतर कैसे प्रभावित करता है? – bevacqua

उत्तर

5

क्या यह अक्सर पढ़ने/सम्मिलित/अपडेट की गई तालिका है? क्या आपके चयन के साथ समवर्ती/सम्मिलित गतिविधि समवर्ती है?

मेरा अनुमान है विलंब विवाद के कारण है।

मैं अपने देव सर्वर पर 17 सेकंड में 18 9 एम पंक्तियों पर गिनती चलाने में सक्षम हूं, लेकिन उस तालिका को मारने के अलावा कुछ भी नहीं है।

आप विवाद या पूर्ण शुद्धता के बारे में भी चिंतित आप कर सकते हैं नहीं कर रहे हैं:

exec sp_spaceused 'MyTableName' जो मेटा डेटा के आधार पर गिनती दे देंगे।

आप एक अधिक सटीक गणना चाहते हैं, लेकिन जरूरी नहीं कि परवाह नहीं है अगर यह समवर्ती DELETE या INSERT गतिविधि आप एक NOLOCK संकेत के साथ अपने वर्तमान क्वेरी कर सकते हैं को प्रतिबिंबित करते हैं:

SELECT COUNT(id) FROM MyTable WITH (NOLOCK) जिसके लिए पंक्ति-स्तर ताले नहीं मिलेगा आपकी क्वेरी और तेजी से चलना चाहिए।

+0

कोई व्यस्त डेटाबेस नहीं है - विवाद कोई मुद्दा नहीं है (कथन लगभग 30 के जवाब देने के लिए लगभग सटीक समय लेता है और नोलोकैक संकेत का उपयोग करने से कोई फर्क नहीं पड़ता।) – BonyT

+0

@ बोनीटी - फिर आपके पास कुछ अन्य समस्याएं हैं। यह टेबल कितनी विस्तृत है? यह 'COUNT' से सीधे प्रासंगिक नहीं है लेकिन यह प्रभावित करता है कि गणना प्राप्त करने के लिए SQL को कितने पृष्ठों को खींचने की आवश्यकता है, जो उच्च मात्रा में महत्वपूर्ण हो सकता है। आपके पास अन्य क्या समस्याएं हैं? – JNK

+0

स्वीकृत, हालांकि कभी भी यह नहीं पता कि वास्तविक समस्या क्या थी/यहां किसी भी एल्स टर्फ पर है और उन्होंने मुझे समझने के लिए एक वर्कअराउंड रखा है। – BonyT

1
use [DatabaseName] 

select tbl.name, dd.rows from sysindexes dd 
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U' 

select sum(dd.rows)from sysindexes dd 
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U' 

इन प्रश्नों का उपयोग कर आप जहां अपने आवश्यकता के अनुसार खंड 0-5 सेकंड

उपयोग के भीतर सभी तालिकाओं 'गिनती लाने सकता है .....

+0

संदर्भ साइट है: http://planetofcoders.blogspot.com/2011/06/how-to-count-all-rows-in-particular.html –

+1

पोस्ट को ध्यान से पढ़ें, उसकी चिंता 'चुनिंदा गणना नहीं है (आईडी) ' – Rahul

2

विचार:

  • उपयोग SELECT COUNT(*) जो "कितने पंक्तियाँ" के लिए सही है (के रूप में ANSI SQL के अनुसार)। यहां तक ​​कि यदि आईडी पीके है और इस प्रकार शून्य नहीं है, तो SQL सर्वर आईडी की गणना करेगा। पंक्तियां नहीं

  • यदि आप अनुमानित गणना के साथ रह सकते हैं, तो sys.dm_db_partition_stats का उपयोग करें। मेरा उत्तर यहाँ देखें: Fastest way to count exact number of rows in a very large table?

  • आप गंदा साथ रह सकते हैं पढ़ता WITH (NOLOCK)

+0

की धीमी कार्यक्षमता यह वास्तव में कोई फर्क नहीं पड़ता क्योंकि ऑप्टिमाइज़र ब्रैकेट के अंदर जो कुछ भी डालता है, उसी प्रभावी ढंग से उसी योजना का उपयोग करता है। हालांकि कुछ लोग "*" का उपयोग करने के बारे में चिंतित हैं। जो कुछ भी इस मुद्दे के लिए अप्रासंगिक है। – BonyT

+0

@ बोनीटी: यदि आपको लगता है कि यह "उग्र" है, तो मेरा सुझाव है कि आप [अंतर] के बारे में मुझे पता है * (http://stackoverflow.com/questions/1221559/count-vs-count1/1221649#1221649) लेकिन गिनती (कोला) गिनती (*) के समान योजना नहीं दे सकता है। इसलिए मेरा सुझाव – gbn

+0

हां हमारे पास है - हम वास्तव में * :) – BonyT

0

का उपयोग एक और विचार: फ़ाइलों 1 एमबी भागों के साथ बढ़ती है, यह फाइल सिस्टम पर खंडित किया जा सकता है। आप इसे SQL द्वारा नहीं देख सकते हैं, आप इसे डिस्क डिफ्रैग्मेंटेशन टूल का उपयोग करके देखते हैं।

संबंधित मुद्दे