समय श्रृंखला डेटा संग्रहीत करने के लिए वास्तव में कोई 'सबसे अच्छा तरीका' नहीं है, और यह ईमानदारी से कई कारकों पर निर्भर करता है। हालांकि, मैं मुख्य रूप से दो कारकों पर ध्यान केंद्रित करने जा रहा हूं, उनके साथ:
(१) यह परियोजना कितनी गंभीर है कि यह स्कीमा को अनुकूलित करने के आपके प्रयास के योग्य है?
(२) आपके क्वेरी एक्सेस पैटर्न वास्तव में क्या होने जा रहे हैं?
उन सवालों को ध्यान में रखते हुए, आइए कुछ स्कीमा विकल्पों पर चर्चा करें।
फ्लैट टेबल
एक फ्लैट टेबल का उपयोग करने का विकल्प प्रश्न (1) से बहुत अधिक है , जहां अगर यह एक गंभीर या बड़े पैमाने पर परियोजना नहीं है, तो आपको स्कीमा के बारे में बहुत अधिक नहीं सोचना आसान होगा, और बस एक फ्लैट टेबल का उपयोग करें, जैसे:
CREATE flat_table(
trip_id integer,
tstamp timestamptz,
speed float,
distance float,
temperature float,
,...);
ऐसे कई मामले नहीं हैं जहां मैं इस पाठ्यक्रम की सिफारिश करूंगा, केवल अगर यह एक छोटी परियोजना है जो आपके समय का बहुत वारंट नहीं करती है।
आयाम और तथ्य
इसलिए, यदि आपने प्रश्न (1) की बाधा को हटा दिया है , और आप अधिक प्रदर्शन स्कीमा चाहते हैं, तो यह विचार करने वाले पहले विकल्पों में से एक है। इसमें कुछ बुनियादी मानदंड शामिल हैं, लेकिन मापा 'तथ्य' मात्रा से 'आयामी' मात्राओं को निकालना।
अनिवार्य रूप से, आप यात्राओं के बारे में जानकारी दर्ज करने के लिए एक तालिका चाहते हैं,
CREATE trips(
trip_id integer,
other_info text);
और टाइमस्टैम्प रिकॉर्ड करने के लिए एक तालिका,
CREATE tstamps(
tstamp_id integer,
tstamp timestamptz);
और अंत में आपके सभी मापा तथ्य, आयाम तालिकाओं के विदेशी प्रमुख संदर्भों के साथ (जो meas_facts(trip_id)
संदर्भ trips(trip_id)
और meas_facts(tstamp_id)
संदर्भ हैं tstamps(tstamp_id)
)
CREATE meas_facts(
trip_id integer,
tstamp_id integer,
speed float,
distance float,
temperature float,
,...);
ऐसा नहीं लग सकता है कि यह सब पहले मददगार है, लेकिन अगर आपके पास उदाहरण के लिए हजारों समवर्ती यात्राएं हैं, तो वे सभी एक बार प्रति सेकंड, दूसरे पर माप ले सकते हैं। उस स्थिति में, आपको tstamps
तालिका में केवल एक प्रविष्टि का उपयोग करने के बजाय, प्रत्येक यात्रा के लिए समय टिकट को फिर से रिकॉर्ड करना होगा ।
केस का उपयोग करें: अगर आप डेटा रिकॉर्ड कर रहे हैं तो कई समवर्ती यात्राएं होती हैं, तो यह मामला अच्छा होगा और आप सभी प्रकार के मापों तक पहुंचने में कोई आपत्ति नहीं करेंगे।
चूंकि Postgres पंक्तियों द्वारा पढ़ा जाता है, किसी भी समय आप चाहते थे, उदाहरण के लिए, speed
किसी दिए गए समय सीमा पर माप, आपको meas_facts
तालिका से पूरी पंक्ति को पढ़ना चाहिए , जो निश्चित रूप से एक क्वेरी को धीमा कर देगा, हालांकि अगर डेटा सेट आप के साथ काम कर रहा है बहुत बड़ा नहीं है, तो आप भी अंतर नोटिस नहीं होगा।
अपने मापा तथ्यों को विभाजित करना
अंतिम खंड को थोड़ा और आगे बढ़ाने के लिए, आप अपने मापों को अलग-अलग तालिकाओं में तोड़ सकते हैं, जहां उदाहरण के लिए मैं गति और दूरी के लिए तालिकाओं को दिखाऊंगा:
CREATE speed_facts(
trip_id integer,
tstamp_id integer,
speed float);
तथा
CREATE distance_facts(
trip_id integer,
tstamp_id integer,
distance float);
बेशक, आप देख सकते हैं कि इसे अन्य मापों तक कैसे बढ़ाया जा सकता है।
केस का उपयोग करें: इसलिए यह आपको क्वेरी के लिए एक जबरदस्त गति नहीं देगा, शायद आपके गति प्रकार के बारे में क्वेरी करते समय गति में केवल एक रैखिक वृद्धि। ऐसा इसलिए है क्योंकि जब आप गति के बारे में जानकारी देखना चाहते हैं, तो आपको speed_facts
तालिका की एक पंक्ति में मौजूद सभी अतिरिक्त, अनावश्यक जानकारी के बजाय केवल तालिका से पंक्तियों को पढ़ने की आवश्यकता है meas_facts
।
तो, आपको केवल एक माप प्रकार के बारे में डेटा के विशाल बल्बों को पढ़ने की आवश्यकता है, आपको कुछ लाभ मिल सकता है। एक दूसरे अंतराल पर आपके 10 घंटे के डेटा के प्रस्तावित मामले के साथ, आप केवल 36,000 पंक्तियाँ पढ़ रहे होंगे, इसलिए आपको ऐसा करने से वास्तव में कोई महत्वपूर्ण लाभ नहीं मिलेगा। हालाँकि, यदि आप 5,000 ट्रिप के लिए गति माप डेटा देख रहे थे, जो लगभग 10 घंटे थे, तो अब आप 180 मिलियन पंक्तियों को पढ़ रहे हैं। इस तरह की क्वेरी के लिए गति में एक रैखिक वृद्धि से कुछ लाभ मिल सकता है, इसलिए जब तक आपको एक समय में माप प्रकार के एक या दो तक पहुंचने की आवश्यकता होती है।
Arrays / HStore / & टोस्ट
आपको शायद इस हिस्से के बारे में चिंता करने की ज़रूरत नहीं है, लेकिन मुझे उन मामलों के बारे में पता है जहाँ यह मायने रखता है। यदि आपको बड़ी मात्रा में समय श्रृंखला डेटा का उपयोग करने की आवश्यकता है, और आप जानते हैं कि आपको एक विशाल ब्लॉक में सभी का उपयोग करने की आवश्यकता है, तो आप एक संरचना का उपयोग कर सकते हैं , जो टोस्ट टेबल्स का उपयोग करेगा , जो अनिवार्य रूप से आपके डेटा को बड़े, संपीड़ित में संग्रहीत करता है। खंडों। इससे डेटा तक त्वरित पहुंच होती है, जब तक कि आपका लक्ष्य सभी डेटा तक पहुंचना है।
एक उदाहरण कार्यान्वयन हो सकता है
CREATE uber_table(
trip_id integer,
tstart timestamptz,
speed float[],
distance float[],
temperature float[],
,...);
इस तालिका tstart
में, सरणी में पहली प्रविष्टि के लिए समय टिकट संग्रहीत करेगा, और प्रत्येक बाद की प्रविष्टि अगले सेकंड के लिए एक पढ़ने का मूल्य होगा। इसके लिए आपको एप्लिकेशन सॉफ़्टवेयर के प्रत्येक सरणी मान के लिए प्रासंगिक समय स्टैम्प का प्रबंधन करना होगा।
एक और संभावना है
CREATE uber_table(
trip_id integer,
speed hstore,
distance hstore,
temperature hstore,
,...);
जहाँ आप अपने माप मानों को जोड़ते हैं (कुंजी, मान) (टाइमस्टैम्प, माप) के जोड़े।
केस का उपयोग करें: यह एक ऐसा कार्यान्वयन है जो संभवतः किसी ऐसे व्यक्ति के लिए बेहतर है जो PostgreSQL के साथ अधिक सहज है, और केवल तभी जब आप अपने एक्सेस पैटर्न के बारे में सुनिश्चित हों, जिसे बल्क एक्सेस पैटर्न की आवश्यकता हो।
निष्कर्ष?
वाह, यह मुझे अपेक्षा से अधिक लंबा हो गया, क्षमा करें। :)
अनिवार्य रूप से, कई विकल्प हैं, लेकिन आप संभवतः दूसरे या तीसरे का उपयोग करके अपने रुपये के लिए सबसे बड़ा धमाका करेंगे, क्योंकि वे अधिक सामान्य मामले में फिट होते हैं।
पुनश्च: आपके आरंभिक प्रश्न में निहित है कि आपके डेटा एकत्र किए जाने के बाद आप अपना डेटा लोड कर रहे होंगे। यदि आप अपने PostgreSQL उदाहरण में डेटा स्ट्रीम कर रहे हैं, तो आपको अपने डेटा अंतर्ग्रहण और क्वेरी कार्यभार दोनों को संभालने के लिए कुछ और काम करने की आवश्यकता होगी, लेकिन हम इसे दूसरी बार छोड़ देंगे। ;)