बड़े डेटासेट पर घंटे के अनुसार समूह


12

MS SQL 2008 का उपयोग कर मैं 2.5 मिलियन रिकॉर्ड से एक औसत क्षेत्र का चयन कर रहा हूं। प्रत्येक रिकॉर्ड एक सेकंड का प्रतिनिधित्व करता है। MyField उन 1 सेकंड के रिकॉर्ड का एक घंटे का औसत है। बेशक सर्वर सीपीयू 100% हिट करता है और चयन में बहुत लंबा समय लगता है। मुझे संभवतः उन औसत मूल्यों को सहेजने की आवश्यकता है ताकि एसक्यूएल को प्रत्येक अनुरोध पर उन सभी रिकॉर्डों का चयन न करना पड़े। क्या किया जा सकता है?

  SELECT DISTINCT
         CONVERT(VARCHAR, [timestamp], 1)+' '+ CAST(DATEPART(Hh,[timestamp]) as VARCHAR) AS TimeStampHour,
         MIN([timestamp]) as TimeStamp,
         AVG(MyField) As AvgField
    FROM MyData
   WHERE TimeStamp > '4/10/2011'
GROUP BY CONVERT(VARCHAR, [timestamp], 1)+' '+ CAST(DATEPART(Hh,[timestamp]) as VARCHAR)
ORDER BY TimeStamp

6
टाइमस्टैम्प एक क्लस्टर इंडेक्स का हिस्सा है? यह होना चाहिए ...

@antisanity - क्यों? वह सीपीयू नहीं डिस्क io को अधिकतम कर रहा है
जैक का कहना है कि शीर्षासनर्स की कोशिश करें ।xyz

जवाबों:


5

क्वेरी का हिस्सा लंबे समय तक सीपीयू को अधिकतम कर रहा है, ग्रुप बीओ क्लॉज में काम करता है और इस तथ्य में कि ग्रुपिंग को हमेशा इस उदाहरण में एक अनइंस्टॉल्ड सॉर्ट की आवश्यकता होती है। जबकि टाइमस्टैम्प क्षेत्र पर एक सूचकांक प्रारंभिक फिल्टर में मदद करेगा यह ऑपरेशन हर पंक्ति पर किया जाना है जो फ़िल्टर से मेल खाता है। इसे तेज करने के लिए एलेक्स द्वारा सुझाए गए कार्य को करने के लिए एक अधिक कुशल मार्ग का उपयोग किया जाता है, लेकिन आपको अभी भी वहाँ एक बड़ी अक्षमता है क्योंकि क्वेरी प्लान का उपयोग करने वाले क्या-क्या फ़ंक्शन संयोजन के साथ आने में सक्षम नहीं है। कोई भी चीज़ जो किसी भी इंडेक्स द्वारा मदद की जाएगी, इसलिए इसे हर पंक्ति के माध्यम से चलाना होगा, पहले ग्रुपिंग वैल्यूज़ की गणना करने के लिए फ़ंक्शंस को चलाना होगा, उसके बाद ही यह डेटा को ऑर्डर कर सकता है और परिणामी ग्रुपिंग पर एग्रीगेट्स की गणना कर सकता है।

तो समाधान किसी भी तरह से प्रक्रिया समूह बनाने के लिए है कि यह एक सूचकांक का उपयोग कर सकता है, या अन्यथा सभी मिलान पंक्तियों पर एक बार विचार करने की आवश्यकता को हटा दें।

आप प्रत्येक पंक्ति के लिए एक अतिरिक्त कॉलम बना सकते हैं, जिसमें समय के साथ-साथ समय हो, और इस तरह के प्रश्नों में उपयोग के लिए इस कॉलम को अनुक्रमित करें। यह आपके डेटा को असामान्य कर रहा है इसलिए "गंदा" लग सकता है, लेकिन यह काम करेगा और भविष्य के उपयोग के लिए सभी समुच्चय को कैशिंग करने से अधिक साफ होगा (और आधार डेटा को बदलकर उस कैश को अपडेट करना)। अतिरिक्त कॉलम को ट्रिगर द्वारा बनाए रखा जाना चाहिए या तर्क संगत कॉलम होने के बजाय, तर्क द्वारा कहीं और बनाए रखा जाना चाहिए, क्योंकि यह उन सभी वर्तमान और भविष्य के स्थानों की गारंटी देगा, जो डेटा सम्मिलित कर सकते हैं या टाइमस्टैम्प कॉलम या मौजूदा पंक्तियों को अपडेट कर सकते हैं, जिसके परिणामस्वरूप नए डेटा बन सकते हैं। स्तंभ। आप अभी भी 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 को स्पिन करने के अलावा और कुछ नहीं करेगा (जब तक कि क्वेरी प्लानर यह नोटिस नहीं करता है कि यह उस स्थिति में एक नो-ऑप होगा जिसमें यह होगा इसे अनदेखा करें और कोई अतिरिक्त सीपीयू समय का उपयोग न करें)।


3

इस प्रश्न को देखें ( एक तारीख को फर्श करें ) इसके अलावा, सब कुछ स्ट्रिंग में परिवर्तित करने से परेशान क्यों है - आप बाद में ऐसा कर सकते हैं (यदि आपको आवश्यकता है)।

  SELECT DISTINCT
         dateadd(hour,datediff(hour,0,[timestamp]),0) AS TimeStampHour,
         MIN([timestamp]) as TimeStamp,
         AVG(MyField) As AvgField
    FROM MyData
   WHERE TimeStamp > '4/10/2011'
GROUP BY dateadd(hour,datediff(hour,0,[timestamp],0);
ORDER BY TimeStamp

1

क्या आप क्वेरी को तेज़ करना चाहते हैं या आप पूछ रहे हैं कि डेटा स्नैपशॉट कैसे बनाया जाए और इसे कैसे बचाया जाए?

यदि आप इसे तेजी से बनाना चाहते हैं, तो आपको निश्चित रूप से टाइमस्टैम्प क्षेत्र पर एक सूचकांक की आवश्यकता है। इसके अलावा, मैं इसे घंटे में बदलने के लिए उपयोग करने का सुझाव दूंगा:

select convert(varchar(13), getdate(), 121)

यदि आपको एक स्नैपशॉट बनाने और बाद में पुन: उपयोग insert intoकरने की आवश्यकता है, तो अपनी क्वेरी से परिणामों के साथ एक नई तालिका बनाने के लिए उपयोग करें। सूचकांक तालिका के अनुसार और इसका उपयोग करें। जो मैं समझता हूं कि आपको TimeStampHour पर एक सूचकांक की आवश्यकता होगी।

इसके अलावा आप एक नौकरी सेट कर सकते हैं जो आपके नए कुल तालिका में दैनिक डेटा एकत्र करता है।


-1

अपने समूह को उस तरह से एक स्ट्रिंग में परिवर्तित करके, आप अनिवार्य रूप से इसे डेटाबेस में हर एक पंक्ति के लिए एक अनइंडैक्सड हिट बना रहे हैं। यह वही है जो आपके प्रदर्शन को मार रहा है। कोई भी आधा सभ्य सर्वर एक साधारण एग्रीगेट को संभालने में सक्षम होगा जैसे कि एक लाख रिकॉर्ड पर ठीक ठीक अगर इंडेक्स का ठीक से उपयोग किया जाए। मैं आपकी क्वेरी को संशोधित करूंगा और आपके टाइमस्टैम्प पर एक संकुल सूचकांक डालूंगा। यह आपके प्रदर्शन की समस्या को हल करने के लिए जा रहा है, जबकि हर घंटे डेटा की गणना बस समस्या को दूर कर रही है।


1
-1 - नहीं आप "इसे डेटाबेस में हर एक पंक्ति के लिए एक अनुत्पादित हिट नहीं बना रहे हैं" - TimeStampपंक्तियों को फ़िल्टर करने के लिए अभी भी किसी भी सूचकांक का उपयोग किया जाएगा
जैक का कहना है कि topanswers.xyz की कोशिश करें

-3

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

यदि आपके पास पैसा है तो आप एक समर्पित प्रक्रिया डेटा इतिहासकार खरीदने पर विचार कर सकते हैं जैसे:

  1. हनीवेल यूनिफ़ॉर्मेंस PHD
  2. ओसिसॉफ्ट पी.आई.
  3. Aspentech IP21
  4. आदि।

ये उत्पाद एक साथ डेटा निष्कर्षण प्रश्नों के तेजी से प्रसंस्करण की अनुमति देते हुए भारी मात्रा में घने समय श्रृंखला डेटा (मालिकाना स्वरूपों में) संग्रहीत कर सकते हैं। क्वेरी में कई डेटा बिंदु (जिन्हें टैग भी कहा जाता है), लंबे समय के अंतराल (महीने / वर्ष) निर्दिष्ट हो सकते हैं, और इसके अतिरिक्त सारांश डेटा गणना (औसत सहित) की एक विस्तृत विविधता भी हो सकती है।

.. और एक सामान्य नोट पर: मैं हमेशा DISTINCTएसक्यूएल लिखते समय कीवर्ड का उपयोग करने से बचने की कोशिश करता हूं । यह शायद ही कभी एक अच्छा विचार है। आपके मामले में आपको अपने खंड में DISTINCTजोड़कर ड्रॉप करने और समान परिणाम प्राप्त करने में सक्षम होना चाहिए ।MIN([timestamp])GROUP BY


1
यह वास्तव में सही नहीं है। एक रिलेशनल डेटाबेस 2.5 मिलियन रिकॉर्ड के लिए पूरी तरह से ठीक है। और वह बहुत सारी तालिकाओं में शामिल नहीं हो रहा है। पहला संकेत जो आपको या तो अपने डेटा को अपभ्रंश करने की आवश्यकता है या एक गैर-संबंधपरक प्रणाली में जाने के लिए है जब आप कई तालिकाओं में बड़े, जटिल जुड़ जाते हैं। पोस्टर का डेटा सेट वास्तव में एक रिलेशनल डेटाबेस सिस्टम के पूरी तरह से स्वीकार्य उपयोग की तरह लगता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.