2009-03-20 22 views
23

आप निम्न संग्रहण और पुनर्प्राप्ति समस्या से कैसे निपटेंगे?कुशलतापूर्वक भंडारण 7.300.000.000 पंक्तियां

मोटे तौर 2.000.000 पंक्तियों प्रत्येक दिन (365 दिन/वर्ष) प्रति पंक्ति निम्नलिखित जानकारी के साथ जोड़ दिया जाएगा:

  • आईडी (अद्वितीय पंक्ति पहचानकर्ता)
  • ENTITY_ID (1 और के बीच मूल्यों पर ले जाता 2.000.000 समावेशी)
  • date_id (प्रत्येक दिन एक के साथ बढ़ी है - 1 और 3.650 (दस वर्ष: 1 * 365 * 10) के बीच मूल्यों पर ले जाएगा)
  • value_1 (1 और 1.000.000 समावेशी के बीच मूल्यों पर लेता है)
  • value_2 (1 और 1.000.000 समावेशी के बीच मानों पर लेता है)

entity_id date_id के साथ संयुक्त अद्वितीय है। इसलिए, प्रति इकाई और तारीख में अधिकतम एक पंक्ति तालिका में जोड़ा जा सकता है। डेटाबेस 10 साल के दैनिक डेटा (7.300.000.000 पंक्तियों (3.650 * 2.000.000)) रखने में सक्षम होना चाहिए।

ऊपर वर्णित वर्ण लिखने के पैटर्न क्या हैं। पढ़ा गया पैटर्न सरल है: सभी प्रश्न एक विशिष्ट entity_id पर किए जाएंगे। अर्थात। entity_id = 12345 का वर्णन करने वाली सभी पंक्तियों को पुनर्प्राप्त करें।

लेनदेन संबंधी समर्थन की आवश्यकता नहीं है, लेकिन संग्रहण समाधान को खुले-सोर्स किया जाना चाहिए। आदर्श रूप में मैं MySQL का उपयोग करना चाहता हूं, लेकिन मैं सुझावों के लिए खुला हूं।

अब - आप वर्णित समस्या से कैसे निपटेंगे?

अद्यतन: मुझे पढ़ने और लिखने के पैटर्न के बारे में विस्तृत करने के लिए कहा गया था। तालिका में लिखने के लिए प्रति दिन एक बैच में किया जाएगा जहां नई 2 एम प्रविष्टियों को एक बार में जोड़ा जाएगा। प्रत्येक सेकेंड में पढ़ने के साथ लगातार पढ़ा जाएगा।

+0

लीप वर्षों के कारण दस साल की संभावना 3650 दिनों की संभावना नहीं है। – unwind

+1

आप इसे कैसे एक्सेस करेंगे? नेटवर्क से PHP से? स्थानीय मशीन पर सी ++ से ...? –

+2

@unwind: अच्छा बिंदु। याद रखने के लिए सही संख्या 4 वर्षों में 1461 दिन है, जो सही होने के करीब है। यह अभी भी सटीक नहीं है, लेकिन त्रुटि तब तक कोई फर्क नहीं पड़ता जब तक कि आपको 100 साल का डेटा न मिल जाए। –

उत्तर

13

उपयोग partitioning। अपने पढ़ने के पैटर्न के साथ आप entity_id हैश द्वारा विभाजन करना चाहते हैं।

+1

मुझे लगता है कि यह सबसे अच्छा समाधान है। यह उदाहरण के लिए 2000 फाइलें खोलने के बिना रिकॉर्ड की संख्या गिनना संभव बनाता है। या तालिका से चुनिंदा गिनती (*) जैसी कुछ है जहां value_1 = 100। आपका डेटा अधिक जिंदा आता है। – tuinstoel

+0

@ एसएलॉट: इसे क्यों चाहिए?यह एक्सेस की लॉगरिदमिक लागत के साथ सूचकांक का उपयोग करेगा। – vartec

+0

@tuinstoel: यह एक उपयोग का मामला नहीं है। उपयोग के मामले एक विशिष्ट इकाई_आईडी द्वारा डेटा लिखते हैं और प्राप्त करते हैं। किसी ऐसे मामले के लिए ऑप्टिमाइज़ करना जो उपयोग केस नहीं है, क्या यह सहायक नहीं है? –

5

आपको इन प्रश्नों को देखने के लिए चाहते हो सकता है:

Large primary key: 1+ billion rows MySQL + InnoDB?

Large MySQL tables

व्यक्तिगत रूप से, मैं भी अपने पंक्ति चौड़ाई की गणना आप कितना बड़ा अपनी मेज की एक विचार देने के लिए के बारे में लगता है कि होगा (पहले लिंक में विभाजन नोट के अनुसार)।

HTH।,

एस

1

पढ़ने के पैटर्न का आपका विवरण पर्याप्त नहीं है। आपको यह बताने की आवश्यकता होगी कि डेटा की कितनी मात्रा में पुनर्प्राप्त किया जाएगा, प्रश्नों में कितनी बार और कितना विचलन होगा।

इससे आपको कुछ कॉलम पर संपीड़न करने पर विचार करने की अनुमति मिल जाएगी।

संग्रह और विभाजन पर भी विचार करें।

28

"अब - आप वर्णित समस्या से कैसे निपटेंगे?सभी प्रश्नों एक विशिष्ट ENTITY_ID पर किया जाएगा "

सरल फ्लैट फ़ाइलें के साथ

यहाँ क्यों

है।" अर्थात।

level1= entity/10000 
level2= (entity/100)%100 
level3= entity%100 

डेटा के प्रत्येक फ़ाइल level1/level2/level3/batch_of_data

तब आप है: ENTITY_ID का वर्णन सभी पंक्तियों को पुनः प्राप्त = 12345 "

आप 2.000.000 संस्थाओं इकाई संख्या के आधार पर है विभाजन। प्रसंस्करण के लिए नमूनों को वापस करने के लिए निर्देशिका के किसी दिए गए भाग में सभी फ़ाइलों को पढ़ें।

यदि कोई संबंधपरक डेटाबेस चाहता है, तो फ़ाइलों को लोड करें उनके उपयोग के लिए डेटाबेस में दिए गए entity_id को दें।


संपादित दिन संख्या पर।

  1. date_id/entity_id विशिष्टता नियम कुछ नहीं है कि नियंत्रित किया जा रहा है। यह (ए) फ़ाइल नामों पर मामूली रूप से लगाया गया है और (बी) पूछताछ के लिए अप्रासंगिक है।

  2. date_id "रोलओवर" का कोई मतलब नहीं है - कोई प्रश्न नहीं है, इसलिए कुछ भी नाम बदलने की आवश्यकता नहीं है। date_id बस युग की तारीख से बंधे बिना बढ़ना चाहिए। यदि आप पुराने डेटा को शुद्ध करना चाहते हैं, तो पुरानी फाइलों को हटा दें।

चूंकि कोई प्रश्न date_id पर निर्भर नहीं है, इसके साथ कभी भी कुछ भी करने की आवश्यकता नहीं है। यह सभी के लिए फ़ाइल नाम हो सकता है।

परिणाम सेट में date_id शामिल करने के लिए, फ़ाइल में प्रत्येक चार पंक्तियों में मौजूद अन्य चार विशेषताओं के साथ फ़ाइल में लिखें।


खोलने/बंद करने

लेखन के लिए पर संपादित, तो आप फ़ाइल (रों) खुला छोड़ने के लिए की है। आप यह सुनिश्चित करने के लिए आवधिक फ्लश (या बंद/दोबारा) करते हैं कि सामान वास्तव में डिस्क पर जा रहा है।

आपके पास अपने लेखक की वास्तुकला के लिए दो विकल्प हैं।

  1. एक भी "लेखक" प्रक्रिया है कि विभिन्न स्रोत (ओं) से डेटा समेकित है। यदि प्रश्न अपेक्षाकृत लगातार होते हैं तो यह सहायक होता है। आप लिखने के समय डेटा विलय करने के लिए भुगतान करते हैं।

  2. कई फाइलें लिखने के लिए समवर्ती रूप से खुली हैं। पूछताछ करते समय, इन फ़ाइलों को एक परिणाम में विलय करें। यह सहायक है प्रश्न पूछना अपेक्षाकृत दुर्लभ है। आप क्वेरी समय पर डेटा विलय करने के लिए भुगतान करते हैं।

+0

मेरे विचार बिल्कुल। – Martin

+0

मैं इसे वोट दे रहा हूं - अक्सर लोग सरल समाधान को याद करते हैं। स्तर 1 में 201 निर्देशिकाएं हैं, स्तर 2 और 3 में प्रत्येक 100 है, अच्छी तरह से किसी भी फाइल सिस्टम की सीमाओं के भीतर। – paxdiablo

+0

मेरी एकमात्र चिंता यह है कि तारीखों को दिन संख्या 1-3650ish के रूप में संग्रहीत किया जाता है। क्या होता है यदि आप 10 साल और 1 दिन तक पहुंच जाते हैं और आपको उन्हें रोल करने की आवश्यकता होती है - यह बहुत सारे नाम बदलें। – paxdiablo

2

मैं similar problem था (हालांकि बहुत बड़ा पैमाने के साथ - अपने वार्षिक उपयोग के बारे में हर दिन) - आप कुछ महीनों खींच सकते हैं लेकिन मैं आपको लगता है कि '

एक बड़ी मेज का उपयोग करते हुए मुझे एक विराम करने के लिए रोते मिला अंततः इसे विभाजित करेंगे।

तालिका को इंडेक्स करना न भूलें, अन्यथा आप प्रत्येक क्वेरी के डेटा की छोटी सी चीज के साथ गड़बड़ कर रहे होंगे; ओह, और यदि आप सामूहिक प्रश्न करना चाहते हैं, use flat files

4

आपके आवेदन में मेरे जैसा ही प्रतीत होता है। मैंने समस्या को कुशलता से हल करने के लिए एक MySQL कस्टम स्टोरेज इंजन लिखा था। यह वर्णन किया गया है here

कल्पना कीजिए अपने डेटा 2M निश्चित लंबाई प्रविष्टियों (इकाई प्रति एक) से युक्त 3650 पंक्तियों 20 बाइट्स की (प्रतिदिन एक) (प्रतिदिन एक इकाई के लिए पंक्ति) की एक सरणी के रूप में डिस्क पर खर्च की गई थी ।

आपका पढ़ा पैटर्न एक इकाई को पढ़ता है। यह डिस्क पर संगत है इसलिए इसमें 1 खोज (लगभग 8mllisecs) लगता है और 3650x20 = लगभग 100 एमबी/सेकेंड पर 80 के बारे में पढ़ता है ... तो यह एक सेकंड के एक अंश में किया जाता है, आसानी से आपके 1-क्वेरी-प्रति-सेकेंड को पढ़ता है पैटर्न।

अद्यतन डिस्क पर 2 एम विभिन्न स्थानों में 20 बाइट्स लिखना है। सबसे सरल मामले में इसमें 2 एम लगेंगे, जिनमें से प्रत्येक में लगभग 8 मिलीलीक्स लगते हैं, इसलिए इसमें 2 एम * 8ms = 4.5 घंटे लगेंगे। यदि आप डेटा को 4 "RAID0" डिस्क में फैलाते हैं तो इसमें 1.125 घंटे लग सकते हैं।

हालांकि स्थान केवल 80K अलग हैं। जिसका मतलब है कि 16 एमबी ब्लॉक (सामान्य डिस्क कैश आकार) के भीतर 200 ऐसे स्थान हैं, इसलिए यह 200 गुना तेज गति से संचालित हो सकता है। (1 मिनट) वास्तविकता दोनों के बीच कहीं है।

मेरा स्टोरेज इंजन उस तरह के दर्शन पर काम करता है, हालांकि यह एक निश्चित लंबाई सरणी से थोड़ा अधिक सामान्य उद्देश्य है।

आप जो भी वर्णन किया है उसे ठीक से कोड कर सकते हैं। एक MySQL प्लगेबल भंडारण इंजन में कोड डालने का मतलब है कि आप विभिन्न रिपोर्ट जनरेटर आदि

वैसे साथ डेटा क्वेरी करने के लिए MySQL का उपयोग करें, आप संग्रहीत पंक्ति से तारीख और इकाई आईडी को समाप्त कर सकता कर सकते हैं (क्योंकि वे कर रहे हैं सरणी अनुक्रमणिका) और अद्वितीय आईडी हो सकती है - यदि आपको वास्तव में इसकी आवश्यकता नहीं है क्योंकि (इकाई आईडी, दिनांक) अद्वितीय है, और 2 मानों को 3-बाइट int के रूप में संग्रहीत करें। फिर आपकी संग्रहीत पंक्ति 6 ​​बाइट्स है, और आपके पास 16 एम प्रति 700 अपडेट हैं और इसलिए एक तेज़ आवेषण और एक छोटी फ़ाइल है।

संपादित फ्लैट फ़ाइलें

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

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

इसलिए यदि आप फ्लैट फाइलों का उपयोग करते हैं, तो क्यों न केवल एक फ्लैट फ़ाइल का उपयोग न करें और इसे अनुक्रमित करें? प्रदर्शन पर

संपादित

इस आवेदन के प्रदर्शन डिस्क से प्रभावित बार की तलाश जा रहा है। मैंने जो गणना की है, वह सर्वोत्तम है जो आप कर सकते हैं (हालांकि आप चयन को धीमा करके INSERT को तेज कर सकते हैं - आप उन्हें दोनों बेहतर नहीं बना सकते हैं)। इससे कोई फर्क नहीं पड़ता कि आप को छोड़कर डेटाबेस, फ्लैट-फाइल्स, या एक फ्लैट-फ़ाइल, का उपयोग करते हैं, जिससे आप अधिक खोज सकते हैं कि आपको वास्तव में आवश्यकता नहीं है और इसे और धीमा कर दें। उदाहरण के लिए, इंडेक्सिंग (चाहे वह फाइल सिस्टम इंडेक्स या डेटाबेस इंडेक्स) "एरे लुकअप" की तुलना में अतिरिक्त I/Os का कारण बनती है, और ये आपको धीमा कर देगी।

संपादित बेंचमार्क माप

पर मैं एक मेज है कि बहुत ज्यादा तुम्हारा (या लगभग ठीक आपके विभाजन में से एक की तरह) की तरह लग रहा है। यह 64K इकाइयां 2 एम (आपके 1/32 का) नहीं था, और 2788 'दिन' थीं। तालिका उसी आईएनएसईआरटी आदेश में बनाई गई थी कि आपका होगा, और उसी सूचकांक (entity_id, दिन) होगा। 2788 दिनों का निरीक्षण करने के लिए एक इकाई पर एक चयन में 20.3 सेकंड लगते हैं, जो प्रति सेकंड लगभग 130 खोजों की अपेक्षा करता है (8 मिलीसेक औसत खोज समय डिस्क पर)। चयन समय दिनों की संख्या के आनुपातिक होने जा रहा है, और संस्थाओं की संख्या पर अधिक निर्भर नहीं है। (यह तेजी से तलाशने वाले समय के साथ डिस्क पर तेज़ होगा। मैं RAID0 में SATA2s की एक जोड़ी का उपयोग कर रहा हूं लेकिन यह बहुत अंतर नहीं कर रहा है)।

तो आप फिर से आदेश से (एंटिटी, DAY) तो एक ही चयन 198 millisecs (क्योंकि यह एक एकल डिस्क उपयोग में आदेश इकाई पढ़ रही है) लेता इकाई आदेश ALTER तालिका एक्स आदेश में तालिका। हालांकि अल्टर टेबल ऑपरेशन को पूरा करने के लिए 13.98 दिन (182 एम पंक्तियों के लिए) लिया गया।

कुछ अन्य चीजें हैं जो माप आपको बताती हैं 1. आपकी अनुक्रमणिका फ़ाइल आपकी डेटा फ़ाइल जितनी बड़ी होगी। यह नमूना तालिका के लिए 3 जीबी है। इसका मतलब है (मेरे सिस्टम पर) डिस्क पर सभी इंडेक्स मेमोरी की गति नहीं है।

2. आपकी INSERT दर लॉगरिदमिक रूप से गिर जाएगी। डेटा फ़ाइल में INSERT रैखिक है लेकिन सूचकांक में कुंजी डालने लॉग है। 180 एम रिकॉर्ड में मुझे प्रति सेकंड 153 आईएनएसईआरटी मिल रहा था, जो कि खोज दर के बहुत करीब है। यह दिखाता है कि MySQL लगभग हर आईएनएसईआरटी के लिए एक पत्ता सूचकांक ब्लॉक अपडेट कर रहा है (जैसा कि आप उम्मीद करेंगे क्योंकि यह इकाई पर अनुक्रमित है लेकिन दिन के क्रम में डाला गया है।)। तो आप 2 एम पंक्तियों के अपने दैनिक सम्मिलन के लिए 2 एम/153 सेकंड = 3.6hrs देख रहे हैं। (सिस्टम या डिस्क में विभाजन द्वारा आप जो भी प्रभाव प्राप्त कर सकते हैं उससे विभाजित)।

0

यदि आप लाखों पंक्तियों के साथ विशाल डेटा को संभालना चाहते हैं तो इसे समय श्रृंखला डेटाबेस के समान माना जा सकता है जो समय को लॉग करता है और डेटा को डेटाबेस में सहेजता है। डेटा स्टोर करने के कुछ तरीके InfluxDB और MongoDB का उपयोग कर रहे हैं।

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