mysqldump से डेटा की धीमी लोड गति


21

मुझे लगभग 30 तालिकाओं के साथ एक मध्यम आकार का MySQL डेटाबेस मिला है, जिनमें से कुछ 10 मिलियन रिकॉर्ड, कुछ 100 मिलियन हैं। mysqldumpसभी तालिकाओं (अलग फ़ाइलों में) का काफी तेजी से होता है, हो सकता है 20 मिनट लगते हैं। यह लगभग 15GB डेटा जेनरेट करता है। सबसे बड़ी डंप की गई फाइलें 2GB रेंज में हैं।

जब मैं MySQL में डेटा को एक अन्य बॉक्स, छह-कोर, 8 जीबी मशीन पर लोड करता हूं, तो यह हमेशा के लिए होता है। आसानी से 12 घड़ी घंटे या अधिक।

मैं फ़ाइल को लोड करने के लिए सिर्फ mysql क्लाइंट चला रहा हूं, अर्थात

mysql database < footable.sql

फ़ाइल सीधे mysqldump से सीधे बाहर

mysqldump database foo > footable.sql

स्पष्ट रूप से मैं कुछ गलत कर रहा हूं। मैं कहां से शुरू करता हूं इसलिए यह उचित समय में खत्म हो सकता है?

मैं डंप या लोड पर किसी भी स्विच का उपयोग नहीं कर रहा हूं।


आप अपने डंप के लोड के दौरान बाइनरी लॉगिंग को भी निष्क्रिय कर सकते हैं
सेड्रिक PEINTRE

जवाबों:


22

इन बिंदुओं को अपने विचार में लें, वे डंप पैदा करने और इसे बहाल करने के मामले में आपकी मदद कर सकते हैं।

  1. Extended insertsडंप में उपयोग करें ।
  2. --tabप्रारूप के साथ डंप करें ताकि आप उपयोग कर सकें mysqlimport, जो कि इससे तेज है mysql < dumpfile
  3. एकाधिक थ्रेड्स के साथ आयात करें, प्रत्येक तालिका के लिए एक।
  4. यदि संभव हो तो एक अलग डेटाबेस इंजन का उपयोग करें। इनोडोड जैसे भारी लेन-देन वाले इंजन में आयात भयानक रूप से धीमा है। MyISAM जैसे एक गैर-लेन-देन इंजन में सम्मिलित करना बहुत तेज़ है।
  5. विदेशी कुंजी जांचें बंद करें और ऑटो-कमिट चालू करें।
  6. यदि आप आयात करने के लिए एक ही सबसे प्रभावी काम कर रहे हैं, तो आप innodb_flush_log_at_trx_commit = 2अपने my.cnf में डाल सकते हैं , अस्थायी रूप से आयात करते समय। ACID की आवश्यकता होने पर आप इसे 1 पर वापस रख सकते हैं

कोशिश तो करो..


आपका इशारा innodb_flush_log_at_trx_commit = 2मेरे दिन को बचाने के साथ । 600 एमबी डंप (एक बड़े लेनदेन के रूप में) को आयात करने में 6 घंटे की आवश्यकता होती है, लेकिन इस अस्थायी सेटिंग के साथ, यह 30 मिनट में किया गया था!
डैनियल मार्शेल

1
जिन चीजों को आप चाहते हैं, उन्हें 'एंटर ’करने के 4 दिन बाद डंप से 80gig डेटाबेस लोड करने की कोशिश करने से पहले पता था ... :)
दिमित्री DB

7

अब्दुल के जवाब के अलावा , मैं --disable-keysविकल्प के महत्व पर जोर देना चाहूंगा , जो कुंजी को बंद कर देता है जब तक कि सभी डेटा एक तालिका के लिए लोड नहीं किया जाता है। यह विकल्प --optटॉगल के भाग के रूप में सक्षम है , जो डिफ़ॉल्ट रूप से सक्षम है, लेकिन इसे इंगित करना महत्वपूर्ण है।

यदि आप आवेषण के दौरान कुंजियों को नहीं छोड़ते हैं, तो सम्मिलित की गई प्रत्येक पंक्ति अनुक्रमणिका का पुनर्निर्माण करेगी। एक बेहद धीमी प्रक्रिया।


है - mysqldump का महत्वपूर्ण हिस्सा? या पुनः लोड करें?
पैट फैरेल

इसे डंप फ़ाइल में जोड़ा जाएगा
डेरेक डाउनी

--optडिफ़ॉल्ट रूप से है
जिब्रीमैन

1
This option is effective only for nonunique indexes of MyISAM tables. It has no effect for other tables
ईथन एलन

7

मैं हाल ही में इसके साथ बहुत काम कर रहा हूं। आप समानांतर में आयात करके निश्चित रूप से आयात प्रदर्शन में सुधार कर सकते हैं। अधिकांश मंदी आई / ओ आधारित है, लेकिन आप अभी भी तालिकाओं में डंप करके 40% सुधार प्राप्त कर सकते हैं और फिर उन्हें एक बार में 4 कहते हैं।

आप इसे इस तरह से xargs के साथ कर सकते हैं:

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

फ़ाइलों को mysql पर धकेलने से पहले gzipped होने से कुछ भी धीमा नहीं होता है क्योंकि ज्यादातर I / O कम होता है। मेरी तालिकाओं को लगभग 10: 1 तक संकुचित किया गया था, इसलिए यह बहुत सारे डिस्क स्थान को बचाता है।

मैंने पाया है कि 4 कोर मशीनों पर, 4 प्रक्रियाओं का उपयोग करना इष्टतम है, हालांकि केवल 3 का उपयोग करने की तुलना में थोड़ा बेहतर है। यदि आपके पास एसएसडी या एक तेज RAID है, तो आप बेहतर पैमाने की संभावना करेंगे।

ध्यान देने योग्य कुछ अन्य बातें। यदि आपके पास 4k सेक्टर ड्राइव हैं, तो सुनिश्चित करें कि आपके पास है key_cache_block_size=4096और myisam_block_size=4K

यदि आप MyISAM तालिकाओं का उपयोग कर रहे हैं, तो myisam_repair_threads = 2उच्चतर सेट करें । यह आपके अतिरिक्त कोर को अनुक्रमित करने में मदद करेगा।

सुनिश्चित करें कि आप बिल्कुल भी स्वैप नहीं कर रहे हैं। यदि आप हैं, के आकार को कम करें innodb_buffer_pool_size

मुझे लगता है कि मुझे इन विकल्पों में से भी कुछ स्पीडअप मिला है:

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(अंतिम तीन मैंने बड़े पैमाने पर परीक्षण नहीं किया - मुझे लगता है कि मैंने उन्हें इंटर्नेट पर सुझाव के रूप में पाया।) ध्यान दें कि इससे innodb_flush_log_at_commit=0mysql के दुर्घटनाग्रस्त होने या बाहर जाने की शक्ति के साथ भ्रष्टाचार हो सकता है।


ग्रेग, साइट पर आपका स्वागत है और आपके उत्तर के लिए धन्यवाद। क्या आप अपने सुझाव के लिए कुछ स्रोत या तर्क प्रदान कर सकते हैं *_block_sizeऔर myisam_repair_threads? इसके अलावा, यह सुनिश्चित नहीं करना चाहिए कि हमें 'इन्टर्नेट्स से सुझाव' के आधार पर वेरिएबल्स ट्यून करने की सलाह देना चाहिए :)
डेरेक डाउनी

5

यदि आपके पास मुख्य रूप से MyISAM टेबल हैं, तो आपको बल्क इंसर्ट बफर को बढ़ाना चाहिए । यहाँ MySQL प्रलेखन थोक_insert_buffer_size सेट करने पर क्या कहता है :

MyISAM INSERT के लिए बड़ी मात्रा में ट्री-इन्सर्ट बनाने के लिए एक विशेष ट्री-जैसे कैश का उपयोग करता है ... चयन करें, INSERT ... VALUES (...), ... (...), और LOAD DATA INFILE जब nonempty में डेटा जोड़ते हैं। टेबल। यह चर बाइट ट्री के आकार को प्रति धागे बाइट्स में सीमित करता है। इसे 0 पर सेट करना इस अनुकूलन को अक्षम करता है। डिफ़ॉल्ट मान 8MB है।

दो चीजें हैं जो आपको करने की आवश्यकता है

1) इसे /etc/my.cnf में जोड़ें

[mysqld]
bulk_insert_buffer_size=512M

2) इसके लिए वैश्विक मूल्य निर्धारित करें

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

यदि आपको वैश्विक स्तर पर बल्क_इन्टर_बफ़र_साइज़ सेट करने का विशेषाधिकार नहीं है, तो ऐसा करें

service mysql restart

बेशक, यह InnoDB के लिए नहीं है।

किसी अन्य कोण से, चाहे तालिकाएँ InnoDB या MyISAM हों, यदि अनुक्रमणिकाएँ तालिका से बड़ी हैं, तो आपके पास बहुत अधिक अनुक्रमणिकाएँ हो सकती हैं। मैं आमतौर पर अनुमान लगाता हूं कि एक MyISAM mysqldump को फिर से लोड करना चाहिए जब तक कि mysqldump बनाने के लिए 3 बार नहीं लग जाता। मैं यह भी स्वीकार करता हूं कि जब तक mysqldump बनाने का समय नहीं लगता, तब तक एक InnoDB mysqldump का पुनः लोड करना चाहिए।

यदि आप mysqldump को पुनः लोड करने के लिए 4: 1 अनुपात से अधिक हो रहे हैं, तो आपको निश्चित रूप से दो समस्याओं में से एक है:

  • बहुत सारे सूचकांक
  • बड़े कॉलमों के कारण इंडेक्स बहुत बड़े होते हैं

आप इसके साथ भंडारण इंजन द्वारा अपने डेटा का आकार माप सकते हैं:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

देखें कि क्या इंडेक्स डेटा जितना बड़ा है या बड़ा है

आप इस तरह से बाइनरी लॉगिंग को अक्षम करने पर भी विचार कर सकते हैं:

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

स्क्रिप्ट को फिर से लोड करने से पहले


मुझे नहीं पता कि आपने मेरा दिन कितनी बार बचाया है लेकिन यह सुनिश्चित है कि बहुत कुछ हुआ है
दिमित्री डीबी

2

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

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy

1

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

  1. बंद करो mysqld
  2. / var / lib / mysql की मौजूदा सामग्री को हटा दें
  3. एक खाली / var / lib / mysql dir बनाएँ
  4. आर-पार tmpfs -o आकार = 32 g tmpfs / var / lib / mysql (आकार समायोजित करें)
  5. एक खाली db बनाएँ (जैसे mysql_install_db, या पिछली सामग्री को पुनर्स्थापित करें)
  6. mysqld शुरू करें
  7. आयात
  8. बंद करो mysqld
  9. copy / var / lib / mysql से mysql2
  10. umount mysql; rmdir mysql
  11. mysql2 को mysql में ले जाएं
  12. mysqld शुरू करो, खुश रहो

मेरे लिए, ~ 10G (/ var / lib / mysql खपत ~ 20G) का एक डंप लगभग 35 मिनट (mydumper / myloader), 45 मिनट (mysqldump --tab / mysqlport), 50 मिनट (mysqldump / mysql) में आयात किया जा सकता है 2x6-कोर 3.2GHz Xeon पर।

यदि आपके पास एक मशीन में पर्याप्त रैम नहीं है, लेकिन तेज नेटवर्क के साथ एक-दूसरे के बगल में कई कंप्यूटर हैं, तो यह देखना दिलचस्प होगा कि क्या उनके रैम को nbd (नेटवर्क ब्लॉक डिवाइस) के साथ जोड़ा जा सकता है। या, innodb_file_per_table के साथ, आप संभवतः प्रत्येक तालिका के लिए उपरोक्त प्रक्रिया दोहरा सकते हैं।


जिज्ञासा से बाहर मैंने 2 जीबी डेटाबेस के लिए SSD (SSDSC2BB48 के इच्छुक लोगों के साथ) की तुलना करने के लिए RAM में mysql डेटादिर को संग्रहीत करने का प्रयास किया। परिणाम IDENTICAL थे, दोनों ने 207-209 सेकंड का समय लिया। इस तथ्य को ध्यान में रखते हुए कि आपको mysql को शुरू करना / रोकना है और निर्देशिकाओं को कॉपी करना है, SSD के बजाय RAM डिस्क का उपयोग करना मेरे मामले में बहुत धीमा था
Shocker

यदि यह आपको ~ 3-4 मिनट का समय लगता है, तो मुझे लगता है कि आपके पास इस विषय के मुकाबले काफी छोटा डेटाबेस है। इस विषय में बताए गए की तुलना में बड़े डेटाबेस के साथ अपने अनुभवों के बारे में सुनना दिलचस्प होगा।
१०:
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.