2016-11-23 6 views
6

मैं एक वेब अनुप्रयोग बना रहा हूं जो एक MySQL डेटाबेस से जुड़ा हुआ है। इस समय मेरे पास दो विशाल टेबल हैं जिनमें प्रत्येक 40 मिलियन पंक्तियां हैं, और वे प्रतिदिन नई पंक्तियां प्राप्त कर रहे हैं (जो हर रोज ~ 500 000-1000 000 पंक्तियां जोड़ती है)।विशाल टेबल पर प्रतिदिन इंडेक्स जोड़ना और छोड़ना एक अच्छा अभ्यास है?

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

बात यह है कि, दिन के दौरान, उन तालिकाओं के खिलाफ कुछ पूरी तरह से अलग प्रश्न चलते हैं, जिनमें कुछ "श्रेणी कहां खंड" (SELECT * FROM t1 WHERE a = a1 AND b = b1 AND (date BETWEEN d1 AND d2)) शामिल हैं। मुझे इस बहुत उपयोगी मिनी-कुकबुक पर स्टैक पर पाया गया है जो आपको सलाह देता है कि डेटाबेस पर पूछे जाने वाले तरीके के आधार पर आपको किस इंडेक्स का उपयोग करना चाहिए: http://mysql.rjweb.org/doc.php/index_cookbook_mysql वे कंपाउंड इंडेक्स का उपयोग करने की सलाह देते हैं: मेरे उदाहरण क्वेरी में इंडेक्स (ए, बी , तारीख)।

यह वास्तव में दिन के दौरान चलने वाले प्रश्नों की गति में वृद्धि (1 मिनट से 8 सेकंड तक तो मैं वास्तव में खुश था)।

हालांकि, उन यौगिक इंडेक्स के साथ, रात के दौरान नई पंक्तियों को जोड़ने के लिए आवश्यक समय पूरी तरह विस्फोट (दैनिक सामग्री जोड़ने में एक से अधिक दिन लगेंगे)।

यहां मेरा प्रश्न है: क्या हर रात सभी इंडेक्स को छोड़ना, नई सामग्री जोड़ना और दैनिक इंडेक्स का बैक अप रखना ठीक है? या यह खतरनाक होगा क्योंकि सूचकांक हर दिन पुनर्निर्मित नहीं किया जाता है, खासकर ऐसी बड़ी तालिकाओं पर? मुझे पता है कि इस तरह के एक ऑपरेशन में कुल दो घंटे लगेंगे (ड्रॉप और इंडेक्स को फिर से बनाएं)।

मुझे ALTER TABLE table_name DISABLE KEYS; के अस्तित्व से अवगत है, लेकिन मैं इनो डीबी का उपयोग कर रहा हूं और मुझे विश्वास है कि यह इनो डीबी टेबल पर काम करने के लिए नहीं बनाया गया है।

किसी भी वरिष्ठ सलाह का स्वागत किया जाएगा! अग्रिम धन्यवाद।

+1

यदि आप हर दिन 500k से 1m नई पंक्तियां जोड़ रहे हैं, तो 1 साल के समय में आपके पास 222 होगा।5 मीटर पंक्तियां, इसलिए वर्तमान राशि से 5 गुना अधिक, यदि वर्तमान में 2 घंटे लगते हैं, तो गति की एक रैखिक गिरावट (असंभव) मानते हुए, इसमें 10 घंटे लगेंगे। दो साल में यह पूरे दिन लगेगा और आप कभी भी एप्लिकेशन का उपयोग करने में सक्षम नहीं होंगे। अगर मैं आप थे तो मैं टेबल विभाजन के बारे में सोचना शुरू कर दूंगा। साथ ही, क्या आपको डेटा को अपने सबसे दानेदार स्तर पर पूछताछ करने की आवश्यकता है? यदि नहीं, तो डेटा को अधिक कुशल बनाने के लिए आप ओलाप डेटाबेस और/या घन को देखना चाहेंगे। – GarethD

+0

आप सही हैं, बढ़ने के लिए पंक्तियों की मात्रा, लेकिन यह अधिकतम राशि तक पहुंच जाएगी क्योंकि मैं नए लोगों को जोड़ने के बाद रोजाना एक वर्ष से अधिक की पंक्तियों को हटा रहा हूं। वैसे भी, मैं उन ओलाप डेटाबेस पर एक नज़र डालने जा रहा हूं। अगर आपके पास कुछ अच्छा दस्तावेज है तो मुझे इसे प्राप्त करने में खुशी होगी! – Tchopane

उत्तर

2

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

मैं के बारे में पूछूंगा कि आप नए डेटा डाल रहे हैं। एक विधि मूल्यों को एक पंक्ति में एक पंक्ति डालना है।

insert into bigtable(. . .) 
    select . . . 
    from smalltable; 

ये अलग-अलग प्रदर्शन विशेषताएं हैं: एक और अस्थायी तालिका (कोई सूचकांक के साथ) में मान रखा और एक थोक डालने करना है। आप पाते हैं कि एक insert (यदि आप पहले से ऐसा नहीं कर रहे हैं) का उपयोग करके अपने उद्देश्यों के लिए पर्याप्त तेज़ है।

+0

ठीक है यह सुनकर अच्छी खबर है कि इस तरह आगे बढ़ना असामान्य नहीं है। अपने प्रश्न का उत्तर देने के लिए, दुर्भाग्यवश मूल्यों को अस्थायी तालिका में रखना असंभव है क्योंकि प्रत्येक नई अतिरिक्त पंक्ति के अगले सामग्री पर प्रभाव पड़ता है। एक नया निर्माण शुरू करने से पहले प्रत्येक बनाई गई पंक्ति को संग्रहीत करने की आवश्यकता होती है। धन्यवाद! – Tchopane

+0

मैंने इस प्रक्रिया को चलाया कि कैसे वर्णित (गिराए गए और रात के सूचकांक निर्मित) और ऐसा लगता है कि यह ठीक काम कर रहा है। पंक्तियों को सम्मिलित करना वास्तव में तेज़ था और एप्लिकेशन अब अपने दैनिक उपयोग के लिए तैयार है। – Tchopane

2

एक digression ... PARTITIONing तिथि के अनुसार आपके लिए बहुत उपयोगी होना चाहिए क्योंकि आप एक साल पहले चीजों को हटा रहे हैं। मैं PARTITION BY RANGE(TO_DAYS(...)) की सिफारिश करता हूं और इसे 14 या 54 विभाजन (महीनों या हफ्तों, साथ ही कुछ ओवरहेड) में तोड़ देता हूं। इससे पुरानी पंक्तियों को हटाने में लगने वाले समय को खत्म कर दिया जाएगा, क्योंकि DROP PARTITION लगभग तात्कालिक है।

अधिक जानकारी my partition blog में हैं।आपकी स्थिति दोनों केस # 1 का उपयोग करें और केस # 3 का उपयोग करें।

लेकिन सूचकांक छोड़ने और पुनर्निर्माण के आपके चालाक विचार पर वापस जाएं। दूसरों के लिए, मैं इस चेतावनी को इंगित करता हूं कि आपके पास पुनर्निर्माण करने के लिए लंबे समय तक तालिका को छूने की लक्जरी नहीं है।

PARTITIONing के साथ, डाली जाने वाली सभी पंक्तियां 'नवीनतम' विभाजन में जाएंगी, सही? यह विभाजन पूरी तालिका से बहुत छोटा है, इसलिए एक बेहतर मौका है कि इंडेक्स रैम में फिट होगा, इस प्रकार अद्यतन करने के लिए 10 गुना तेजी से (इंडेक्स के पुनर्निर्माण के बिना) हो सकता है। यदि आप SHOW CREATE TABLE, SHOW TABLE STATUS, innodb_buffer_pool_size, और रैम आकार प्रदान करते हैं, तो मैं यह देखने के लिए अंकगणित करने में आपकी सहायता कर सकता हूं कि आपका 'अंतिम' विभाजन रैम में फिट होगा या नहीं।

इनो डीबी में इंडेक्स अपडेट के बारे में एक नोट - वे "चेंज बफर" में बैठकर 'देरी' कर रहे हैं, जो बफर_पूल का एक हिस्सा है। 5.6 से उपलब्ध innodb_change_buffer_size_max देखें। क्या आप उस संस्करण का उपयोग कर रहे हैं, या नए? (यदि नहीं, तो आपको कई कारणों से अपग्रेड करना चाहिए।)

उस सेटिंग के लिए डिफ़ॉल्ट 25 है, जिसका अर्थ है कि INSERT आदि के कारण इंडेक्स में लंबित अपडेट के लिए 25% बफर_पूल सेट किया गया है। एक "कैश" की तरह कार्य करता है, जैसे कि उसी इंडेक्स ब्लॉक के कई अपडेट तब तक आयोजित किए जाते हैं जब तक वे बाहर नहीं निकलते। एक उच्च सेटिंग को सूचकांक अद्यतनों को डिस्क को कम बार कम करना चाहिए, इसलिए तेज़ी से समाप्त करें।

जहां मैं इसके साथ आगे बढ़ रहा हूं ... इस सेटिंग को बढ़ाकर, आप आवेषण (सीधे, पुनर्निर्माण नहीं) अधिक कुशल बना देंगे। मैं सोच रहा हूँ यह यह गति हो सकता है कि ऊपर:

बस हर रात को INSERTs से पहले:

innodb_change_buffer_size_max = 70 
innodb_old_blocks_pct = 10 

जल्द ही हर रात को INSERTs के बाद:

innodb_change_buffer_size_max = 25 
innodb_old_blocks_pct = 37 

(मुझे लगता है कि अन्य सेटिंग के बारे में निश्चित नहीं हूँ , लेकिन इसे रास्ते से बाहर धक्का देना उचित लगता है।)

इस बीच, innodb_buffer_pool_size की सेटिंग क्या है? आमतौर पर, यह उपलब्ध रैम का 70% होना चाहिए।

इसी तरह के एक आवेदन में, मेरे पास एक टेबल में लोड करने के लिए बड़ा, प्रति घंटा, डंप था, और एक 90-दिन प्रतिधारण। मैंने 9 0 दैनिक विभाजन और 24 घंटे के विभाजन के साथ अपने विभाजन नियमों को बढ़ाया। हर रात, मैंने 24 घंटे के विभाजन को एक नए दैनिक (और 90-दिन पुराने विभाजन को छोड़ने) के लिए REORGANIZE PARTITION करने में बहुत समय बिताया (लेकिन एक घंटे से भी कम)। प्रत्येक घंटे के दौरान, भार में अतिरिक्त लाभ था कि 1 घंटे के विभाजन को छूने वाला कुछ भी नहीं था - मैं सामान्यीकरण, संक्षेपण और 7 मिनट में सभी को लोड कर सकता था। पूरे 90 दिन 400 जीबी में फिट बैठते हैं। (साइड नोट: बड़ी संख्या में विभाजन 8.0 तक एक प्रदर्शन हत्यारा है; इसलिए 1-वर्ष प्रतिधारण के लिए दैनिक विभाजन भी नहीं मानें।)

सारांश सारणीएं ताकि 50 मिनट के प्रश्न (प्रोटोटाइप में) केवल 2 सेकंड तक गिर गया। शायद आपको PRIMARY KEY (a, b, date) के साथ सारांश तालिका की आवश्यकता है? इससे आपको 'तथ्य' तालिका पर ऐसी अनुक्रमणिका से छुटकारा मिल जाएगा। ओह, जो आपके मूल प्रश्न के पूरे आधार को समाप्त करता है! मेरे ब्लॉग के नीचे दिए गए लिंक देखें; "सारांश सारणी" के लिए देखो। एक सामान्य नियम: तथ्य तालिका पर कोई अनुक्रमणिका नहीं है (PRIMARY KEY के अलावा); उन चीज़ों के लिए सारांश सारणी का उपयोग करें जिन्हें मैसियर इंडेक्स की आवश्यकता है।

+0

सबसे पहले, इस विस्तृत उत्तर के लिए धन्यवाद। मुझे लगता है कि मैं वास्तव में विभाजन का उपयोग करने जा रहा हूं। लेकिन तिथियों पर नहीं, चूंकि डेटा कालक्रम में जोड़ा गया है: मैं प्राथमिक कुंजी का उपयोग कर सकता हूं, जो एक ऑटो वृद्धिशील पूर्णांक है, जिससे मैं इच्छित सामग्री को आसानी से हटा सकता हूं। और मुझे लगता है कि सही ढंग से चुने गए विभाजन मुझे दिन के दौरान अपने आवेदन को तेज करने में मदद कर सकते हैं। इसके अलावा, ऐप का उपयोग किए बिना हर रात कम से कम 6 घंटे अभी भी है, इसलिए मेरे पास अभी भी उस दैनिक हटाने का सत्र प्रबंधित करने की क्षमता कम है। – Tchopane

+0

वैसे, आपके ब्लॉग पर उन सभी सलाहयों को इकट्ठा करने के लिए धन्यवाद, यह वास्तव में सहायक है और यह निश्चित रूप से मुझे सही विभाजन बनाने में मदद करेगा। मुझे उन सारांश तालिकाओं पर एक नज़र डालेंगी। :) मेरी MySQL कॉन्फ़िगरेशन के बारे में, मैं वर्तमान में MySQL 5.7 का उपयोग कर रहा हूं और innodb_buffer_pool_size पहले से उपलब्ध RAM के 70% पर सेट है। innodb_change_buffer_max_size का वर्तमान मान वास्तव में 25 है; आवेषण कितनी तेज़ी से मूल्यांकन करने के लिए मैं इसे अगली रात 70 तक बढ़ाने की कोशिश करूंगा। – Tchopane

+0

कृपया अपने प्रयोग पर change_buffer_max_size के साथ रिपोर्ट करें। –

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