5

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

विज़ुअलाइज़ेशन उद्देश्यों के लिए, मैंने एक संग्रहीत प्रक्रिया बनाई है जो एक मशीन और डेटापॉइंट की पहचान करने के लिए आवश्यक दो आईडी लेती है, और एक प्रारंभ और अंत डेटाटाइम भी होती है। फिर यह वैरिएबल लम्बाई (आमतौर पर 15 मिनट, 1 घंटा, 7 दिन इत्यादि) के हिस्सों में प्रारंभ और अंत के बीच के मानों को जोड़ता है और दिए गए समय अंतराल के भीतर प्रत्येक खंड के लिए औसत, न्यूनतम और अधिकतम मान देता है।

यह विधि काम करती है, लेकिन इसमें बहुत सारे समय होते हैं, यहां तक ​​कि बहुत सारे डीबी अनुकूलन और अनुक्रमणिका के साथ भी। तो फ्रंटएंड चार्ट पेज पर चयनित श्रेणी और मशीन के लिए डेटा प्रदर्शित करने में लगभग 10 से 60 सेकंड लगते हैं, जो मुझे लगता है कि बहुत अधिक है।

इसलिए मैंने एक नई तालिका बनाने के बारे में सोचना शुरू किया जिसमें प्रत्येक मशीन के लिए प्रत्येक "खंड" के लिए पूर्व-समेकित डेटा शामिल है। इसे प्राप्त करने के लिए, समेकन प्रक्रिया को प्रत्येक मशीन के लिए प्रत्येक [chunksize] मिनट/घंटे/दिन स्वचालित रूप से कॉल करना होगा। कोसरर चंक्स को आसानी से बेहतर हिस्सों से बनाया जा सकता था, जहां तक ​​मैं देख सकता हूं, यह नाटकीय रूप से पूरी चीज को गति देगा।

सवाल यह है कि आवधिक एकत्रीकरण को लागू करने का सबसे अच्छा तरीका क्या है? डेटाबेस को अपना काम करने का कोई तरीका है? या क्या मुझे एएसपी.नेट एमवीसी वेब एप्लिकेशन के भीतर एक टाइमर-आधारित समाधान लागू करना है? उत्तरार्द्ध को वेब ऐप को हमेशा चलाने की आवश्यकता होगी, जो संभवतः सबसे अच्छा तरीका नहीं है क्योंकि यह विभिन्न कारणों से नीचे हो सकता है। एक और विकल्प एक स्वतंत्र आवेदन या सेवा होगी जो इस कार्य का ख्याल रखती है। क्या कोई अन्य तरीका है जिसके बारे में मैंने नहीं सोचा था? आप इस मुद्दे से कैसे संपर्क करेंगे?

+1

आप ऐसा करने के लिए एसक्यूएल सर्वर में एक [निर्धारित नौकरी] (https://msdn.microsoft.com/en-us/library/ms191439.aspx) का उपयोग कर सकते हैं। –

+0

यह आशाजनक लग रहा है, धन्यवाद! आपके व्यापक उत्तर के लिए – Robert

उत्तर

6

हमारे सिस्टम में हमारे पास मूल कच्चे डेटा वाला एक टेबल है। इस कच्चे डेटा को प्रति घंटा, दैनिक और साप्ताहिक अंतराल (योग, न्यूनतम, प्रत्येक अंतराल के लिए कच्चे मूल्यों का अधिकतम) में सारांशित किया जाता है।

हम 30 दिनों (4 सप्ताह) के लिए कच्चे डेटा, 43 दिनों (6 सप्ताह) के लिए प्रति घंटा, दैनिक 560 दिनों (18 महीने) के लिए प्रतिदिन, साप्ताहिक 10 वर्षों के लिए रखते हैं। हर रात इन चार तालिकाओं को "साफ" किया जाता है और थ्रेसहोल्ड से पुराना डेटा हटा दिया जाता है। प्रति घंटा तालिका में लगभग 30 एम पंक्तियां होती हैं, दैनिक 18 एम पंक्तियां होती हैं। कुछ रिपोर्ट/चार्ट प्रति घंटा डेटा का उपयोग करते हैं, अधिकतर दैनिक डेटा का उपयोग करते हैं। कभी-कभी हमें किसी समस्या की विस्तृत जांच के लिए कच्चे डेटा को देखने की आवश्यकता होती है।

मेरे पास सी ++ में लिखा गया एक समर्पित एप्लिकेशन है, जो सर्वर पर चलता है 24/7 और ~ 200 अन्य सर्वरों से कच्चे डेटा एकत्र करता है और इसे केंद्रीय डेटाबेस में सम्मिलित करता है। आवेदन के अंदर मैं समय-समय पर (हर 10 मिनट) एक संग्रहीत प्रक्रिया को कॉल करता हूं जो सारांशों को फिर से समझता है। यह संग्रहीत प्रक्रिया किसी भी समय अंतिम उपयोगकर्ता द्वारा चलाया जा सकता है, यदि उपयोगकर्ता नवीनतम डेटा देखना चाहता है। आमतौर पर इसे चलाने में लगभग 10 सेकंड लगते हैं, इसलिए आम तौर पर अंतिम उपयोगकर्ता देर से सारांश देखता है। तो, तकनीकी रूप से सर्वर पर एक निर्धारित नौकरी हो सकती है जो हर 10 मिनट में प्रक्रिया चलाती है। जब मैं इसे किसी एप्लिकेशन के माध्यम से करता हूं तो मेरे पास डेटा एकत्र करने वाले अन्य धागे पर बेहतर नियंत्रण होता है। अनिवार्य रूप से, मैं संक्षेप में होने पर नए डेटा को सम्मिलित करने का प्रयास रोकता हूं। लेकिन, केवल स्वतंत्र संग्रहित प्रक्रियाओं का उपयोग करके एक ही प्रभाव प्राप्त करना संभव है।

मेरे मामले में मैं सारांशों का पुनर्मूल्यांकन बल्कि कुशल बना सकता हूं।

  • चूंकि इस 10 मिनट की विंडो के दौरान डेटाबेस में नया डेटा बहता है, इसलिए मैं कच्ची डेटा सीधे मुख्य तालिका में डालता हूं। कच्चे डेटा बिंदु कभी अपडेट नहीं होते हैं, वे केवल जोड़े जाते हैं (सम्मिलित)।तो, यह कदम सरल और कुशल है। मैं संग्रहित प्रक्रिया का उपयोग टेबल-मूल्य वाले पैरामीटर के साथ करता हूं और एक कॉल में नए डेटा का एक हिस्सा पास करता हूं। इस प्रकार एक पंक्ति में INSERT कथन में कई पंक्तियां डाली जाती हैं, जो अच्छी है।

  • सारांश तालिका को दूसरी संग्रहीत प्रक्रिया का उपयोग करके हर 10 मिनट में नए डेटा के साथ अपडेट किया जाता है। मौजूदा पंक्तियों में से कुछ को अद्यतन किया जाना चाहिए, कुछ पंक्तियां जोड़ दी गई हैं। इसे कुशलतापूर्वक करने के लिए मेरे पास मशीन की आईडी, प्रति घंटा दिनांक-समय, दैनिक दिनांक-समय, साप्ताहिक दिनांक-समय कॉलम के साथ एक अलग "स्टेजिंग" तालिका है। चूंकि मैं मुख्य तालिका में कच्चा डेटा डालता हूं, इसलिए मैं इस स्टेजिंग तालिका में प्रभावित मशीन आईडी और प्रभावित समय अंतराल भी डालता हूं।

तो, दो मुख्य संग्रहित प्रक्रियाएं हैं। कई थ्रेड का उपयोग करके 200 रिमोट सर्वर के माध्यम से एप्लिकेशन लूप करता है और एक अनंत लूप में प्रत्येक सर्वर से ताजा डेटा डाउनलोड करता है। जैसे ही कुछ रिमोट सर्वर से डेटा के ताजा बैच को डाउनलोड किया जाता है, पहली संग्रहीत प्रक्रिया को बुलाया जाता है। यह अक्सर होता है। यह प्रक्रिया कच्ची डेटा में कच्चे डेटा के बैच को "स्टेजिंग" तालिका में प्रभावित समय अंतराल की सूची के रूप में सम्मिलित करती है।

कहो, कच्चे आंकड़ों के भेजे बैच इस तरह दिखता है:

ID timestamp   raw_value 
1 2015-01-01 23:54:45 123 
1 2015-01-01 23:57:12 456 
1 2015-01-02 00:03:23 789 
2 2015-01-02 02:05:21 909 

4 पंक्तियों मुख्य तालिका के रूप में (आईडी, टाइमस्टैम्प, मूल्य) में डाला जाता है।

3 पंक्तियों मचान तालिका में डाला जाता है (आम तौर पर एक ही घंटे से टाइमस्टैम्प के साथ मूल्यों का एक बहुत होते हैं, इसलिए मचान तालिका में कच्चे पंक्तियों का एक बहुत है, लेकिन कुछ देखते हैं):

ID hourlytimestamp  dailytimestamp  weeklytimestamp 
1 2015-01-01 23:00:00 2015-01-01 00:00:00 2014-12-29 00:00:00 
1 2015-01-02 00:00:00 2015-01-02 00:00:00 2014-12-29 00:00:00 
2 2015-01-02 00:00:00 2015-01-02 00:00:00 2014-12-29 00:00:00 

ध्यान दें, कि यहां मैं सभी आईडी और टाइमस्टैम्प को अद्वितीय सेट में मिला/मिला/मिला हूं और इस स्टेजिंग टेबल में मूल्य नहीं हैं, इसमें केवल प्रभावित आईडी और समय अंतराल होते हैं (StatsToRecalc यह स्टेजिंग तालिका है, @ParamRows पैरामीटर है संग्रहित प्रक्रिया के जिसमें नए डेटा के साथ पंक्तियों का बैच है):

DECLARE @VarStart datetime = '20000103'; -- it is Monday 
INSERT INTO dbo.StatsToRecalc 
    (ID 
    ,PeriodBeginLocalDateTimeHour 
    ,PeriodBeginLocalDateTimeDay 
    ,PeriodBeginLocalDateTimeWeek) 
SELECT DISTINCT 
    TT.[ID], 
    -- Truncate time to 1 hour. 
    DATEADD(hour, DATEDIFF(hour, @VarStart, TT.PlaybackStartedLocalDateTime), @VarStart), 
    -- Truncate time to 1 day. 
    DATEADD(day, DATEDIFF(day, @VarStart, TT.PlaybackStartedLocalDateTime), @VarStart), 
    -- Truncate time to 1 week. 
    DATEADD(day, ROUND(DATEDIFF(day, @VarStart, TT.PlaybackStartedLocalDateTime)/7, 0, 1) * 7, @VarStart) 
FROM @ParamRows AS TT; 

फिर से कच्चे तालिका में INSERT सरल है।

तो, 10 मिनट के लिए कई धागे से इस प्रक्रिया का उपयोग करके कच्चे और स्टेजिंग टेबल में कई INSERTS हैं।

हर 10 मिनट में दूसरी प्रक्रिया जो सारांश को पुन: गणना करती है उसे बुलाया जाता है।

पहली बात यह है करता है एक सौदे शुरू होता है और लेन-देन के अंत तक मचान तालिका ताले:

SELECT @VarCount = COUNT(*) 
FROM dbo.StatsToRecalc 
WITH (HOLDLOCK) 

तो मचान तालिका StatsToRecalc खाली नहीं है, हम कुछ करने की जरूरत है। चूंकि यह तालिका लॉक है, सभी काम करने वाले धागे हस्तक्षेप नहीं करेंगे और अधिक डेटा जोड़ने से पहले पुनर्मूल्यांकन समाप्त होने तक प्रतीक्षा करेंगे।

इस स्टेजिंग टेबल का उपयोग करके मैं जल्दी से निर्धारित कर सकता हूं कि कौन से घंटों, दिन और हफ्तों के लिए मुझे आईडी को पुन: गणना करने की आवश्यकता है। वास्तविक सारांश गणना MERGE कथन में की जाती है, जो सभी प्रभावित आईडी और अंतराल को एक बार में संसाधित करती है। मैं तीन MERGEs को कच्चे डेटा को प्रति घंटा सारांश में समेटने के लिए चलाता हूं, फिर प्रति घंटे प्रतिदिन और फिर साप्ताहिक में। फिर स्टेजिंग टेबल खाली हो जाती है (हर 10 मिनट), इसलिए यह कभी भी बड़ा नहीं होता है।

पहली बार में प्रत्येक MERGE (उदाहरण के लिए, प्रति घंटा से दैनिक तालिका अद्यतन करने के लिए) आईडी और timestamps की एक सूची है कि पिछले पुनर्गणना के बाद से प्रभावित हुए हैं बनाता है:

WITH 
CTE_Changed (ID, PeriodBeginLocalDateTimeDay) 
AS 
(
    SELECT 
     dbo.StatsToRecalc.ID 
     , dbo.StatsToRecalc.PeriodBeginLocalDateTimeDay 
    FROM 
     dbo.StatsToRecalc 
    GROUP BY 
     dbo.StatsToRecalc.ID 
     ,dbo.StatsToRecalc.PeriodBeginLocalDateTimeDay 
) 

और फिर इस CTE के साथ प्रति घंटा की तालिका संयोजन MERGE:

MERGE INTO dbo.StatsDay AS Dest 
USING 
(
    SELECT 
     ...     
    FROM 
     dbo.StatsHour 
     INNER JOIN CTE_Changed ON 
      CTE_Changed.ID = dbo.StatsHour.ID AND 
      CTE_Changed.PeriodBeginLocalDateTimeDay = dbo.StatsHour.PeriodBeginLocalDateTimeDay 
) 
... 

इस बहुमंज़िला संक्षेप मैं कच्चे में सहायक कॉलम है, प्रति घंटा और दैनिक तालिकाओं के साथ मदद करने के लिए।

2015-01-01 22:00:00 
2015-01-01 23:00:00 
2015-01-02 00:00:00 
2015-01-02 01:00:00 
... 

, एक घंटे की अर्थात सीमाओं: उदाहरण के लिए, प्रति घंटा की मेज एक स्तंभ PeriodBeginLocalDateTimeHour जो इस तरह के मूल्यों रखती है। PeriodBeginLocalDateTimeDay है, जो इस तरह के मूल्यों रखती है::

2015-01-01 00:00:00 
2015-01-02 00:00:00 
... 

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

मुझे जोड़ना चाहिए, कि मेरे मामले में यह ठीक है अगर उस समर्पित सी ++ एप्लिकेशन थोड़ी देर के लिए नीचे था। इसका मतलब यह है कि डेटा 10 मिनट से अधिक समय तक देरी होगी, लेकिन कुछ भी खो जाएगा नहीं।

+0

Thansk! यह एक दिलचस्प दृष्टिकोण है। मैं वर्तमान में अनुसूचित नौकरियों के साथ खेल रहा हूं जो ज़ोहर ने ऊपर वर्णित किया है। आपके टेबल लेआउट पर एक टिप्पणी: यदि आप पहले से ही समेकित "दैनिक" मानों से "साप्ताहिक" मान बनाए हैं (जिन्हें "प्रति घंटा" मानों से गणना की जाती है, तो यह अधिक प्रदर्शनकारी नहीं होगा, ताकि आपको पुन: गणना करने की आवश्यकता न हो सभी स्टेजिंगटेबल पंक्तियों से बार-बार? – Robert

+1

@Robert, यह वही है जो मैं करता हूं। मैंने जवाब में और विवरण जोड़ा है। स्टेजिंग टेबल का उपयोग कच्चे, फिर प्रति घंटा, फिर दैनिक सारणी में उन आईडी और उन घंटों, दिन और हफ्तों को कुशलतापूर्वक खोजने के लिए किया जाता है जिन्हें अपडेट किया जाना चाहिए। रिमोट सर्वर से डेटा 10 मिनट तक बह रहा है। इस समय के दौरान कौन से सर्वर संसाधित किए गए हैं? रिमोट सर्वर कुछ दिनों के लिए नीचे हो सकता था - सर्वर से प्राप्त टाइमस्टैम्प क्या हैं? (वे 20 मिनट या 2 दिन पुराने हो सकते हैं) स्टेजिंग टेबल इन सवालों का कुशलता से जवाब देती है। शायद "स्टेजिंग" इसके लिए एक अच्छा नाम नहीं है ... –

+0

आप सही हैं, अब मुझे मिल गया है। अपने समाधान को साझा करने के लिए धन्यवाद, यह दूसरों के लिए एक अच्छा प्रारंभिक बिंदु है। – Robert