1 बिलियन पंक्तियों और गिनती को संभालने के लिए डेटाबेस डिजाइन


10

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

समस्या यह है कि ऐसा लगता है कि डेटाबेस डेटा डालने की दर के साथ संघर्ष करने के लिए संघर्ष कर रहा है। कभी-कभी जब लोड बढ़ता है, तो डालने का समय अचानक काफी बढ़ जाता है (> 30 सेकंड), जो बदले में अधिक डेटा को बफर करने की अनुमति देता है, जिसके परिणामस्वरूप बड़े आवेषण और लंबे समय तक डालने की अवधि होती है।

मुझे उम्मीद है कि वर्तमान डिज़ाइन पर कुछ टिप्पणियां, और कुछ विचारों को हमें प्रदर्शन में सुधार करना होगा, और हमारे कुछ सवालों के जवाब - और किसी भी अन्य लोगों के सुझाव हो सकते हैं!

मौजूदा डिज़ाइन

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

टेबल डिजाइन

  • आईडी (पीके, अद्वितीय पहचानकर्ता)
  • DeviceId (FK, int)
  • व्यक्ति (FK, int)
  • वाहन आई (FK, int)
  • टोकनएड (FK, int)
  • UtcTime (पीके, डेटाटाइम 2 (3))
  • अक्षांश (फ्लोट)
  • देशांतर (नाव)
  • गति (छोटा)
  • शीर्षक (छोटा)
  • उपग्रह (छोटे)
  • IOData (वैरिएंट (100))
  • इग्निशनस्टैट (टिनींट)
  • UserInput (छोटे)
  • CreateTimeUtc (datetime2 (3))

सूचकांकों

  • DeviceId_CreateTimeUtc_Desc
  • DeviceId_UtcTime_Desc (क्लस्टर किया गया)
  • PersonId_UtcTime_Desc
  • TokenId_UtcTime_Desc
  • VehicleId_UtcTime_Desc

हर हफ्ते वर्तमान में सूचकांकों सहित लगभग 10 जीबी लगते हैं, और वर्तमान में मुख्य डेटाबेस में लगभग 300 जीबी डेटा है।

मुख्य डेटाबेस में डेटा टेबल के पास 1 फ़ाइल के साथ अपना स्वयं का फ़ाइलग्रुप है, लेकिन यह मुख्य डेटाबेस में अन्य सभी तालिकाओं के समान डिस्क पर है। द्वितीयक डेटाबेस एक अलग डिस्क पर है, लेकिन एक ही मशीन पर।

मुझे लगता है कि जब हम एक नया टेबल विभाजन (सप्ताह) उपयोग में लिया जाता है, तो हम एक इंडेक्स रिबूट जॉब साप्ताहिक भी चला रहे हैं। कोई संकोचन नहीं किया जाता है।

मशीन 12-जीबी मेमोरी के साथ एक 8-कोर एचपी है, और मुख्य डेटाबेस को पकड़ने वाली डिस्क RAID 10 चल रही है।

विचार

  • प्राथमिक डेटाबेस में संग्रहीत डेटा की मात्रा को अधिकतम 1 महीने तक सीमित करें। बहुत कम से कम यह डेटाबेस को बैकअप / बहाली के लिए अधिक प्रबंधनीय बना देगा, लेकिन क्या हम ऐसा करके प्रदर्शन में सुधार देखने की उम्मीद कर सकते हैं?
  • वर्तमान डेटा के लिए फ़ाइल समूह में 2 फ़ाइलें बनाएँ, और उन्हें 2 अलग-अलग भौतिक विभाजनों पर वितरित करें
  • वर्तमान डेटा रखने वाले मास्टर-स्लेव डेटाबेस बनाएँ, इसलिए आवेषण और रीड विभिन्न डेटाबेस पर किए जाते हैं
  • SSD डिस्क पर वर्तमान डेटा के लिए फ़ाइलें रखें (क्या SSD डिस्क के साथ प्रदर्शन में कोई बदलाव होगा?)

कृपया मुझे बताएं कि क्या अधिक जानकारी की आवश्यकता है। प्रदर्शन को प्रभावित करने वाले कई कारक हैं, और शायद इसे ट्विक करने के कई तरीके हैं।


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
पॉल व्हाइट 9

जवाबों:


8

प्रति मिनट 5000 आवेषण प्रति सेकंड 83 आवेषण होते हैं। 5 इंडेक्स के साथ प्रति सेकंड 400 भौतिक पंक्तियाँ सम्मिलित की जाती हैं। यदि कार्यभार स्मृति में था, तो यह सर्वर के सबसे छोटे स्तर पर भी समस्या उत्पन्न नहीं करेगा। यहां तक ​​कि अगर यह सबसे अक्षम तरीके का उपयोग करके एक पंक्ति-दर-पंक्ति सम्मिलित था, जिसके बारे में मैं सोच सकता हूं। प्रति सेकंड 83 तुच्छ प्रश्न सीपीयू दृष्टिकोण से दिलचस्प नहीं हैं।

शायद, आप डिस्क-बाउंड हैं। आप प्रतीक्षा आंकड़ों को देखकर या इसे सत्यापित कर सकते हैं STATISTICS IO

आपके प्रश्न संभवतः बहुत सारे अलग-अलग पृष्ठों को छूते हैं ताकि बफर पूल में उन सभी के लिए जगह न रहे। यह लगातार पृष्ठ पढ़ता है और शायद यादृच्छिक डिस्क भी लिखता है।

एक तालिका की कल्पना करें जहां आप केवल भौतिक रूप से बढ़ती हुई कुंजी के कारण अंत में सम्मिलित होते हैं। काम करने वाला सेट एक पेज होगा: आखिरी वाला। यह अनुक्रमिक IO उत्पन्न करेगा और साथ ही आलसी लेखक या चेकपॉइंट प्रक्रिया को डिस्क पर तालिका का "अंत" लिखता है।

बेतरतीब ढंग से रखा आवेषण के साथ एक तालिका की कल्पना करें (क्लासिक उदाहरण: एक गाइड कुंजी)। यहां, सभी पृष्ठ काम कर रहे सेट हैं क्योंकि प्रत्येक डालने के लिए एक यादृच्छिक पृष्ठ स्पर्श किया जाएगा। IO यादृच्छिक हैं। यह सबसे खराब स्थिति है जब यह काम करने के सेट पर आता है।

तुम बीच में हो। आपके सूचकांक संरचना के हैं (SomeValue, SequentialDateTime)। पहला घटक आंशिक रूप से दूसरे द्वारा प्रदान की गई अनुक्रमिकता को अनियमित करता है। मुझे लगता है कि " SomeValue" के लिए कुछ संभावित मूल्य हैं ताकि आपके अनुक्रमित में कई बेतरतीब ढंग से सम्मिलित सम्मिलित बिंदु हों।

आप कहते हैं कि डेटा प्रति सप्ताह 10GB टेबल में विभाजित है। यह एक अच्छा शुरुआती बिंदु है क्योंकि काम करने वाला सेट अब 10GB से घिरा हुआ है (किसी भी रीड को नापसंद करते हुए आप ऐसा कर सकते हैं)। 12GB सर्वर मेमोरी के साथ, यह संभावना नहीं है, हालांकि, सभी प्रासंगिक पेज मेमोरी में रह सकते हैं।

यदि आप साप्ताहिक "विभाजन" के आकार को कम कर सकते हैं या सर्वर मेमोरी को थोड़ा बढ़ा सकते हैं तो आप शायद ठीक हैं।

मुझे उम्मीद है कि सप्ताह की शुरुआत में आवेषण तेजी से अंत में हैं। आप एक निश्चित डेटा आकार के साथ एक बेंचमार्क चलाकर और धीरे-धीरे सर्वर मेमोरी को कम कर सकते हैं जब तक कि आप प्रदर्शन टैंक नहीं देखते हैं।

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

एक त्वरित समाधान के रूप में मैं ग्राहकों और मुख्य तालिका के बीच एक बफरिंग परत जोड़ूंगा। शायद 15 मिनट के लेखन को एक मंचन तालिका में जमा करें और समय-समय पर इसे फ्लश करें। यह लोड स्पाइक्स को दूर ले जाता है और बड़ी तालिका में लिखने के लिए अधिक कुशल योजना का उपयोग करता है।


1
@usr बहुत व्यापक और अच्छी तरह से समझाया जवाब के लिए धन्यवाद! हमने वास्तव में सर्वर मेमोरी को बढ़ाने पर चर्चा की है, यह जाने बिना कि इसका कितना प्रभाव होगा - लेकिन अब हमारे पास वास्तव में ऐसा करने के लिए एक बहुत ही आकर्षक कारण है :) आप सही हैं कि "SomeValue" आंशिक रूप से सम्मिलित बिंदुओं को यादृच्छिक बनाता है - शायद लगभग 10000 डिवाइस आईडी। मंचन तालिका के बारे में, क्या आपका सुझाव बिना किसी सूचकांकों के तालिका है, और फिर हर X मिनट में मुख्य तालिका में सम्मिलित करने के लिए एक नौकरी है?
सोनडरगार्ड

@usr Reg अनुक्रमित होने के लिए क्लस्टर इंडेक्स को परिवर्तित करने के लिए आपका सुझाव, हम एक ऑटो-इंक जोड़ सकते हैं। पहचान कॉलम (पूर्णांक), और अनुक्रमिक रखने के एकमात्र उद्देश्य के लिए इस कॉलम में क्लस्टर किए गए सूचकांक को बदल दें? यह तालिकाओं में अद्वितीय नहीं होगा, लेकिन जब तक प्राथमिक कुंजी है, हमें ठीक होना चाहिए।
सोनडरगार्ड

1
यदि स्टेजिंग टेबल छोटी है और आपकी क्वेरी इसके साथ रह सकती है तो आपको बिल्कुल भी इंडेक्स करने की आवश्यकता नहीं है। लेकिन आप कर सकते थे ।; एक रणनीति सीआई को एक पहचान स्तंभ पर बनाने की होगी (जैसा कि आप कहते हैं)। यदि सीआई बड़ा है और अन्य सूचकांक छोटे हैं तो यह अद्भुत काम कर सकता है। क्योंकि CI लिख रहे हैं अब अनुक्रमिक हैं वे आपकी समस्या में बहुत कम योगदान देते हैं। सार्थक आकार अंतर होने पर यह रणनीति सबसे सफल है ।; एक और विचार प्रति दिन एक टेबल होगा। शायद मासिक विलय हो।
usr

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

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