mysql

2016-09-26 9 views
6

के साथ बहुत बड़ा डेटा हैंडलिंग लंबे पोस्ट के लिए खेद है!mysql

मैं एक डेटाबेस युक्त ~ 30 तालिकाओं (InnoDB इंजन) है। इन तालिकाओं में से केवल दो, अर्थात्, "लेनदेन" और "शिफ्ट" काफी बड़े हैं (पहले में 1.5 मिलियन पंक्तियां हैं और शिफ्ट में 23k पंक्तियां हैं)। अब सबकुछ ठीक काम करता है और मुझे वर्तमान डेटाबेस आकार में कोई समस्या नहीं है।

हालांकि, हमारे पास एक समान डेटाबेस (समान डेटाटाइप, डिज़ाइन, ..) होगा, लेकिन बहुत बड़ा, उदाहरण के लिए, "लेनदेन" तालिका में लगभग 1 अरब रिकॉर्ड (लगभग 2,3 मिलियन लेनदेन प्रति दिन) होगा और हम इस बारे में सोच रहे हैं कि हमें MySQL में इस तरह के डेटा के साथ कैसे निपटना चाहिए? (यह दोनों पढ़ा और गहन लिखना है)। मैंने यह देखने के लिए कई संबंधित पोस्ट पढ़ी हैं कि क्या MySQL (और अधिक विशेष रूप से InnoDB इंजन) अरबों रिकॉर्ड के साथ अच्छा प्रदर्शन कर सकता है, लेकिन फिर भी मेरे पास कुछ प्रश्न हैं। उन संबंधित पोस्ट कि मैं पढ़ा है में से कुछ निम्नलिखित हैं:

मैं अब तक क्या समझ लिया है बहुत बड़ी तालिकाओं के लिए प्रदर्शन में सुधार करने के लिए: (InnoDB तालिकाओं जो मेरे मामले है के लिए)

  1. बढ़ती innodb_buffer_pool_size (रैम उदाहरण के लिए, 80%)। इसके अलावा, मैंने पाया कुछ अन्य MySQL प्रदर्शन ट्यूनिंग, सेटिंग here in percona blog
  2. तालिका
  3. MySQL Sharding या क्लस्टरिंग

यहाँ मेरी सवाल कर रहे हैं विभाजन (प्रश्नों पर Explan का प्रयोग करके)

  • मेज पर उचित अनुक्रमित होने/भ्रम:

    • विभाजन के बारे में, मुझे कुछ संदेह हैं कि हमें इसका उपयोग करना चाहिए या नहीं। एक तरफ कई लोगों ने टेबल को बहुत बड़ा होने पर प्रदर्शन में सुधार करने का सुझाव दिया। दूसरी तरफ, मैंने कई पदों को पढ़ा है कि यह क्वेरी प्रदर्शन में सुधार नहीं करता है और यह क्वेरी को तेज़ी से नहीं चलाता है (उदाहरण के लिए, here और here)। इसके अलावा, मैं MySQL Reference Manual में पढ़ा कि InnoDB विदेशी कुंजी और MySQL विभाजन संगत नहीं हैं (हम विदेशी कुंजी है)।

    • अनुक्रमित के बारे में, अभी वे बेहतर प्रदर्शन करेंगे, लेकिन जहां तक ​​मैं समझ गया, बहुत बड़ी तालिकाओं के लिए अनुक्रमण अधिक प्रतिबंधात्मक है (के रूप में केविन बेडेल उसके जवाब here में उल्लेख किया है)। इसके अलावा, लिखने धीमा (सूचकांक/अद्यतन) धीमा होने पर इंडेक्स गति को पढ़ता है। तो, नई समान परियोजना के लिए हमारे पास यह बड़ा डीबी होगा, क्या हमें पहले सभी डेटा डालने/लोड करना चाहिए और फिर अनुक्रमणिका बनाना चाहिए? (सम्मिलित करने के लिए गति)

    • यदि हम अपनी बड़ी तालिका ("लेनदेन" तालिका) के लिए विभाजन का उपयोग नहीं कर सकते हैं, तो प्रदर्शन में सुधार करने के लिए वैकल्पिक विकल्प क्या है? (MySQL चर सेटिंग्स जैसे innodb_buffer_pool_size को छोड़कर)। क्या हमें माइस्क्ल क्लस्टर्स का उपयोग करना चाहिए?(हम मिलती है की भी बहुत)

    संपादित

    यह हमारा सबसे बड़ा तालिका "लेन-देन" नाम के लिए show create table कथन है:

    CREATE TABLE `transaction` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `terminal_transaction_id` int(11) NOT NULL, 
    `fuel_terminal_id` int(11) NOT NULL, 
    `fuel_terminal_serial` int(11) NOT NULL, 
    `xboard_id` int(11) NOT NULL, 
    `gas_station_id` int(11) NOT NULL, 
    `operator_id` text NOT NULL, 
    `shift_id` int(11) NOT NULL, 
    `xboard_total_counter` int(11) NOT NULL, 
    `fuel_type` int(11) NOT NULL, 
    `start_fuel_time` int(11) NOT NULL, 
    `end_fuel_time` int(11) DEFAULT NULL, 
    `preset_amount` int(11) NOT NULL, 
    `actual_amount` int(11) DEFAULT NULL, 
    `fuel_cost` int(11) DEFAULT NULL, 
    `payment_cost` int(11) DEFAULT NULL, 
    `purchase_type` int(11) NOT NULL, 
    `payment_ref_id` text, 
    `unit_fuel_price` int(11) NOT NULL, 
    `fuel_status_id` int(11) DEFAULT NULL, 
    `fuel_mode_id` int(11) NOT NULL, 
    `payment_result` int(11) NOT NULL, 
    `card_pan` text, 
    `state` int(11) DEFAULT NULL, 
    `totalizer` int(11) NOT NULL DEFAULT '0', 
    `shift_start_time` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `terminal_transaction_id` (`terminal_transaction_id`,`fuel_terminal_id`,`start_fuel_time`) USING BTREE, 
    KEY `start_fuel_time_idx` (`start_fuel_time`), 
    KEY `fuel_terminal_idx` (`fuel_terminal_id`), 
    KEY `xboard_idx` (`xboard_id`), 
    KEY `gas_station_id` (`gas_station_id`) USING BTREE, 
    KEY `purchase_type` (`purchase_type`) USING BTREE, 
    KEY `shift_start_time` (`shift_start_time`) USING BTREE, 
    KEY `fuel_type` (`fuel_type`) USING BTREE 
    ) ENGINE=InnoDB AUTO_INCREMENT=1665335 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT 
    

    अपने समय के लिए धन्यवाद,

  • +1

    हेहे - "लंबी पोस्ट" उपज "लंबा जवाब"। –

    +2

    कोकीन एक हेलुवा दवा है। –

    उत्तर

    12
    • क्या MySQL उचित रूप से अरबों पंक्तियों पर प्रश्न कर सकता है? - MySQL अरबों पंक्तियों को 'संभाल' सकता है। "उचित" प्रश्नों पर निर्भर करता है; चलो उन्हें देखते हैं।

    • क्या बहु-अरब पंक्तियों के लिए सही विकल्प है InnoDB (MySQL 5.5.8)? - 5.7 में कुछ सुधार हैं, लेकिन लगभग 6 साल के होने के बावजूद 5.5 बहुत अच्छा है, और अब समर्थित नहीं होने के कगार पर।

    • अरबों पंक्तियों के लिए सर्वश्रेष्ठ डेटा स्टोर - यदि आपका मतलब 'इंजन' है, तो InnoDB।

    • प्रदर्शन से पहले एक MySQL डेटाबेस कितना बड़ा हो सकता है - फिर से, यह प्रश्नों पर निर्भर करता है। मैं आपको एक 1 के पंक्ति तालिका दिखा सकता हूं जो मंदी होगी; मैंने अरब-पंक्ति वाली टेबलों के साथ काम किया है जो साथ हैं।

    • क्यों MySQL बड़ी तालिकाओं के साथ धीमा हो सकता है? - रेंज स्कैन I/O की ओर ले जाता है, जो धीमा हिस्सा है।

    • क्या माइस्क्ल टेबल को 300 मिलियन रिकॉर्ड रख सकता है? - फिर, हाँ। सीमा कहीं ट्रिलियन पंक्तियों के आसपास है।

    • (innoDB टेबल के लिए जो मेरा मामला है) innodb_buffer_pool_size (उदा।, 80% रैम तक) बढ़ रहा है। इसके अलावा, मुझे पेकोना ब्लॉग में कुछ अन्य MySQL प्रदर्शन चौंकाने वाली सेटिंग्स मिलीं - हाँ

    • तालिका पर उचित अनुक्रमणिका (क्वेरी पर एक्सप्लान का उपयोग करके) - ठीक है, चलो देखते हैं। इस महत्वपूर्ण क्षेत्र में कई गलतियां की जा सकती हैं।

    • तालिका को विभाजित करना - "विभाजन एक पैनसिया नहीं है!" मैं my blog

    • MySQL Sharding में है कि पर वीणा - वर्तमान में यह DIY है

    • MySQL क्लस्टरिंग - वर्तमान में सर्वश्रेष्ठ उत्तर कुछ Galera आधारित विकल्प होता है (PXC, MariaDB 10, DIY डब्ल्यू/ओरेकल)

    • विभाजन FOREIGN KEY या "वैश्विक" UNIQUE का समर्थन नहीं करता है।

    • यूयूआईडीएस, जिस पैमाने पर आप बात कर रहे हैं, वह सिस्टम को धीमा नहीं करेगा, बल्कि वास्तव में इसे मार देगा। Type 1 UUIDs एक कामकाज हो सकता है।

    • सम्मिलित करें और इंडेक्स-बिल्ड गति - एक उत्तर देने के लिए बहुत सारे बदलाव हैं। आइए आपके टेटेक्टिव CREATE TABLE और आप डेटा को फ़ीड करने का इरादा रखते हैं।

    • बहुत सारे शामिल हैं - "सामान्य करें, लेकिन अधिक सामान्य नहीं करें।" विशेष रूप से, डेटाटाइम या फ्लोट या अन्य "निरंतर" मानों को सामान्यीकृत न करें।

    • प्रतिदिन summary tables

    • 2,3 लाख लेनदेन का निर्माण करते हैं - अगर वह 2.3M आवेषण (30/सेक), तो वहाँ एक प्रदर्शन समस्या के ज्यादा नहीं है। यदि अधिक जटिल है, तो RAID, एसएसडी, बैचिंग, आदि आवश्यक हो सकता है।

    • डेटा की इस तरह की मात्रा के साथ सौदा - यदि अधिकांश गतिविधि "हालिया" पंक्तियों के साथ है, तो बफर_पूल गतिविधि को अच्छी तरह से 'कैश' करेगा, जिससे I/O से परहेज किया जाएगा। यदि गतिविधि "यादृच्छिक" है, तो MySQL (या कोई भी और) में I/O समस्याएं होंगी।

    +0

    एक और आइटम - "माईएसQL एनडीबी क्लस्टर" गैलेरा से अलग है; एनडीबी का एक आला बाजार है; यह _might_ आपके लिए उपयोगी हो; आइए अपने ऐप के बारे में और देखें। विस्तृत उत्तर के लिए –

    +0

    धन्यवाद रिक। अब मेरी मुख्य चिंता यह है कि मुझे यकीन नहीं है कि हमें क्लस्टरिंग करना चाहिए या नहीं (मैंने इसे पहले कभी नहीं किया है)। मेरा मतलब है कि हमें यह कब करना चाहिए और जब हमें नहीं करना चाहिए? क्लस्टरिंग से पहले मुझे किन कारकों पर विचार करना चाहिए? और अगर हमें यह करना है, तो मुझे कहां से शुरू करना चाहिए? – mOna

    +0

    इसके अलावा, आपने कहा कि आपको प्रश्न देखना चाहिए (अनुक्रमण, प्रदर्शन, ..) के लिए। मुझे प्रश्नों के बारे में क्या जानकारी चाहिए? हमारे ऐप के बारे में आपको क्या जानकारी चाहिए? मैं आपको प्रश्न कैसे दिखा सकता हूं? (क्षमा करें अगर यह बेवकूफ सवाल है!) – mOna

    2

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

    ऐसा करने से आपके अधिकांश प्रश्नों और चिंताओं को खत्म कर दिया जाएगा, साथ ही प्रोसेसिंग तेज हो जाएगी।

    +1

    मैं सहमत हूं। यह मूल रूप से प्रसंस्करण की एक ही मात्रा कर रहा है, लेकिन एक ही समय के बजाय समय के साथ फैल गया। – Aeolun

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