क्वेरी का हिस्सा लंबे समय तक सीपीयू को अधिकतम कर रहा है, ग्रुप बीओ क्लॉज में काम करता है और इस तथ्य में कि ग्रुपिंग को हमेशा इस उदाहरण में एक अनइंस्टॉल्ड सॉर्ट की आवश्यकता होती है। जबकि टाइमस्टैम्प क्षेत्र पर एक सूचकांक प्रारंभिक फिल्टर में मदद करेगा यह ऑपरेशन हर पंक्ति पर किया जाना है जो फ़िल्टर से मेल खाता है। इसे तेज करने के लिए एलेक्स द्वारा सुझाए गए कार्य को करने के लिए एक अधिक कुशल मार्ग का उपयोग किया जाता है, लेकिन आपको अभी भी वहाँ एक बड़ी अक्षमता है क्योंकि क्वेरी प्लान का उपयोग करने वाले क्या-क्या फ़ंक्शन संयोजन के साथ आने में सक्षम नहीं है। कोई भी चीज़ जो किसी भी इंडेक्स द्वारा मदद की जाएगी, इसलिए इसे हर पंक्ति के माध्यम से चलाना होगा, पहले ग्रुपिंग वैल्यूज़ की गणना करने के लिए फ़ंक्शंस को चलाना होगा, उसके बाद ही यह डेटा को ऑर्डर कर सकता है और परिणामी ग्रुपिंग पर एग्रीगेट्स की गणना कर सकता है।
तो समाधान किसी भी तरह से प्रक्रिया समूह बनाने के लिए है कि यह एक सूचकांक का उपयोग कर सकता है, या अन्यथा सभी मिलान पंक्तियों पर एक बार विचार करने की आवश्यकता को हटा दें।
आप प्रत्येक पंक्ति के लिए एक अतिरिक्त कॉलम बना सकते हैं, जिसमें समय के साथ-साथ समय हो, और इस तरह के प्रश्नों में उपयोग के लिए इस कॉलम को अनुक्रमित करें। यह आपके डेटा को असामान्य कर रहा है इसलिए "गंदा" लग सकता है, लेकिन यह काम करेगा और भविष्य के उपयोग के लिए सभी समुच्चय को कैशिंग करने से अधिक साफ होगा (और आधार डेटा को बदलकर उस कैश को अपडेट करना)। अतिरिक्त कॉलम को ट्रिगर द्वारा बनाए रखा जाना चाहिए या तर्क संगत कॉलम होने के बजाय, तर्क द्वारा कहीं और बनाए रखा जाना चाहिए, क्योंकि यह उन सभी वर्तमान और भविष्य के स्थानों की गारंटी देगा, जो डेटा सम्मिलित कर सकते हैं या टाइमस्टैम्प कॉलम या मौजूदा पंक्तियों को अपडेट कर सकते हैं, जिसके परिणामस्वरूप नए डेटा बन सकते हैं। स्तंभ। आप अभी भी MIN (टाइमस्टैम्प) को बाहर निकाल सकते हैं। इस तरह से क्वेरी का क्या परिणाम होगा अभी भी सभी पंक्तियों के नीचे चलना है (इसे टाला नहीं जा सकता है, जाहिर है) लेकिन यह इसे सूचकांक क्रम में कर सकता है, प्रत्येक समूहीकरण के लिए एक पंक्ति का उत्पादन करना क्योंकि यह सूचकांक में अगले मान को प्राप्त करने के बजाय समूहबद्ध / एकत्रीकरण से पहले एक अनइंडैक्सड सॉर्ट ऑपरेशन के लिए पंक्तियों के पूरे सेट को याद रखने के लिए होता है। यह बहुत कम मेमोरी का भी उपयोग करेगा, क्योंकि इसे अभी या उनके बाकी हिस्सों को देखने के लिए पूर्व समूहन मूल्यों से किसी भी पंक्तियों को याद रखने की आवश्यकता नहीं होगी।
यह विधि पूरे परिणाम सेट के लिए मेमोरी में कहीं न कहीं खोज की आवश्यकता को हटाती है और समूह संचालन के लिए अनइंडैक्सड सॉर्ट करती है और बड़ी क्वेरी से समूह मानों की गणना को हटा देती है (उस नौकरी को अलग-अलग INSERTs / UPDATEs के लिए जो उत्पादन करती है) डेटा) और ऐसे प्रश्नों को एकत्रित परिणामों के एक अलग स्टोर को बनाए रखने की आवश्यकता के बिना स्वीकार्य रूप से चलाने की अनुमति देनी चाहिए।
एक विधि जो नहीं हैअपने डेटा को असामान्य करें, लेकिन फिर भी अतिरिक्त संरचना की आवश्यकता होती है, "टाइम टेबल" का उपयोग करना है, इस मामले में हर समय एक पंक्ति प्रति घंटे जिसमें आप विचार करने की संभावना रखते हैं। यह तालिका एक DB या प्रशंसनीय आकार में अंतरिक्ष की एक महत्वपूर्ण राशि का उपभोग नहीं करेगी - 100 साल के एक समय-सारणी को कवर करने के लिए दो तिथियों की एक पंक्ति (घंटे की शुरुआत और अंत), जैसे कि '2011-01-01 @ 00: 00: 00.0000 ',' 2011-01-01 @ 00: 00: 59.9997 ', "9997" मिलीसेकंड की सबसे छोटी संख्या होने के नाते एक DATETIME फ़ील्ड अगले सेकंड तक गोल नहीं होगा) जो दोनों का हिस्सा हैं गुच्छेदार प्राथमिक कुंजी ~ 14 मीटर की जगह लेगी (8 + 8 बाइट्स प्रति पंक्ति * 24 घंटे / दिन * 365.25 दिन / वर्ष * 100, प्लस क्लस्टर इंडेक्स के ट्री संरचना के ओवरहेड के लिए थोड़ा सा है लेकिन यह ओवररिट महत्वपूर्ण नहीं होगा) ।
SELECT CONVERT(VARCHAR, [timestamp], 1)+' '+ CAST(DATEPART(Hh,[timestamp]) as VARCHAR) AS TimeStampHour
, MIN([timestamp]) as TimeStamp
, AVG(MyField) As AvgField
FROM TimeRangeByHours tt
INNER JOIN MyData md ON md.TimeStamp BETWEEN tt.StartTime AND tt.EndTime
WHERE tt.StartTime > '4/10/2011'
GROUP BY tt.StartTime
ORDER BY tt.StartTime
इसका मतलब यह है कि क्वेरी प्लानर का उपयोग करने के लिए MyData.TimeStamp पर सूचकांक की व्यवस्था कर सकता है। क्वेरी प्लानर को यह काम करने के लिए पर्याप्त उज्ज्वल होना चाहिए कि वह MyData.TimeStamp पर अनुक्रमणिका के साथ कदम ताल में नीचे आ सकता है, फिर से एक पंक्ति को समूहीकरण और प्रत्येक समूह या पंक्तियों को छोड़ने के रूप में यह अगले समूहीकरण मूल्य को हिट करता है। रैम में कहीं भी सभी मध्यवर्ती पंक्तियों को संग्रहीत नहीं किया जाता है, फिर उन पर एक अनइंडेक्स प्रकार का प्रदर्शन किया जाता है। बेशक इस विधि के लिए आवश्यक है कि आप टाइम टेबल बनाएं और सुनिश्चित करें कि यह काफी पीछे और आगे दोनों तरफ फैला हो, लेकिन आप अलग-अलग प्रश्नों में कई डेट फील्ड्स के खिलाफ टाइम टेबल का उपयोग कर सकते हैं, जहां "अतिरिक्त कॉलम" विकल्प की आवश्यकता होगी। प्रत्येक दिनांक फ़ील्ड के लिए इस तरह से फ़िल्टर / समूह और तालिका के छोटे आकार के लिए एक अतिरिक्त गणना किए गए कॉलम (जब तक कि आपको 10 की अवधि के लिए इसकी आवश्यकता न हो,
टाइम टेबल विधि में आपकी वर्तमान स्थिति और गणना किए गए कॉलम सॉल्यूशन की तुलना में एक अतिरिक्त अंतर (जो काफी फायदेमंद हो सकता है) है: यह उन समयों के लिए पंक्तियाँ लौटा सकता है जिनके लिए कोई डेटा नहीं है, बस ऊपर उदाहरण उदाहरण में INNER JOIN बदलकर एक व्यक्ति एक होने के लिए।
कुछ लोग सुझाव देते हैं कि उनके पास भौतिक समय सारणी नहीं है, बल्कि हमेशा इसे टेबल रिटर्निंग फ़ंक्शन से लौटाते हैं। इसका मतलब है कि समय सारणी की सामग्री कभी भी संग्रहीत नहीं है (या पढ़ने की आवश्यकता है) डिस्क पर और यदि फ़ंक्शन अच्छी तरह से लिखा गया है, तो आपको इस बारे में चिंता करने की ज़रूरत नहीं है कि समय तालिका को आगे और पीछे कितने समय तक चलने की आवश्यकता है, लेकिन मैं संदेह है कि प्रत्येक क्वेरी के लिए कुछ पंक्तियों के लिए इन-मेमोरी टेबल के उत्पादन की सीपीयू लागत, बनाने (और बनाए रखने की परेशानी की छोटी बचत के लायक है, इसके टाइमपेन को आपके प्रारंभिक संस्करण की सीमा से आगे बढ़ाने की आवश्यकता है) भौतिक समय सारणी।
एक ओर ध्यान दें: आपको अपनी मूल क्वेरी पर DISTINCT क्लाज की आवश्यकता नहीं है। समूहीकरण यह सुनिश्चित करेगा कि ये प्रश्न केवल एक पंक्ति में प्रति अवधि के तहत विचाराधीन हैं, इसलिए DISTINCT CPU को स्पिन करने के अलावा और कुछ नहीं करेगा (जब तक कि क्वेरी प्लानर यह नोटिस नहीं करता है कि यह उस स्थिति में एक नो-ऑप होगा जिसमें यह होगा इसे अनदेखा करें और कोई अतिरिक्त सीपीयू समय का उपयोग न करें)।