यह प्रश्न स्टैक ओवरफ्लो से रिपॉजिट किया गया है जो टिप्पणियों में एक सुझाव पर आधारित है, दोहराव के लिए माफी।
प्रशन
प्रश्न 1: जैसे-जैसे डेटाबेस टेबल का आकार बड़ा होता जाता है, मैं LOAD DATA INFILE कॉल की गति बढ़ाने के लिए MySQL को कैसे ट्यून कर सकता हूं?
प्रश्न 2: विभिन्न सीएसवी फ़ाइलों को लोड करने, प्रदर्शन में सुधार करने या इसे मारने के लिए कंप्यूटर के एक क्लस्टर का उपयोग करना होगा? (यह लोड डेटा और बल्क आवेषण का उपयोग करने के लिए कल मेरी बेंच-मार्किंग का काम है)
लक्ष्य
हम छवि खोज के लिए फीचर डिटेक्टरों और क्लस्टरिंग मापदंडों के विभिन्न संयोजनों की कोशिश कर रहे हैं, जिसके परिणामस्वरूप हमें समय पर फैशन में बड़े डेटाबेस बनाने और सक्षम होने की आवश्यकता है।
मशीन की जानकारी
मशीन में 256 गिग रैम है और डेटाबेस को वितरित करके निर्माण समय में सुधार करने का एक तरीका है, तो राम की समान मात्रा के साथ अन्य 2 मशीनें उपलब्ध हैं?
टेबल स्कीमा
तालिका स्कीमा जैसा दिखता है
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| match_index | int(10) unsigned | NO | PRI | NULL | |
| cluster_index | int(10) unsigned | NO | PRI | NULL | |
| id | int(11) | NO | PRI | NULL | auto_increment |
| tfidf | float | NO | | 0 | |
+---------------+------------------+------+-----+---------+----------------+
के साथ बनाया
CREATE TABLE test
(
match_index INT UNSIGNED NOT NULL,
cluster_index INT UNSIGNED NOT NULL,
id INT NOT NULL AUTO_INCREMENT,
tfidf FLOAT NOT NULL DEFAULT 0,
UNIQUE KEY (id),
PRIMARY KEY(cluster_index,match_index,id)
)engine=innodb;
अब तक की बेंचमार्किंग
पहला कदम एक बाइनरी फ़ाइल से खाली तालिका में थोक आवेषण बनाम लोडिंग की तुलना करना था।
It took: 0:09:12.394571 to do 4,000 inserts with 5,000 rows per insert
It took: 0:03:11.368320 seconds to load 20,000,000 rows from a csv file
प्रदर्शन में अंतर को देखते हुए, मैं एक बाइनरी सीएसवी फ़ाइल से डेटा लोड करने के साथ चला गया हूं, पहले मैंने नीचे दिए गए कॉल का उपयोग करके 100K, 1M, 20M, 200M पंक्तियों से युक्त बाइनरी फ़ाइलों को लोड किया था।
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
मैंने 2 घंटे के बाद 200M पंक्ति बाइनरी फ़ाइल (~ 3 जीबी सीएसवी फ़ाइल) लोड को मार दिया।
इसलिए मैंने तालिका बनाने के लिए एक स्क्रिप्ट चलाई, और एक बाइनरी फ़ाइल से अलग-अलग पंक्तियों को सम्मिलित किया, फिर तालिका को गिरा दिया, नीचे दिया गया ग्राफ़ देखें।
बाइनरी फ़ाइल से 1M पंक्तियों को सम्मिलित करने में लगभग 7 सेकंड का समय लगा। आगे मैंने एक समय में 1M पंक्तियों को बेंचमार्क करने का फैसला किया, यह देखने के लिए कि क्या किसी विशेष डेटाबेस आकार में एक अड़चन होने वाली है। एक बार जब डेटाबेस ने लगभग 59M पंक्तियों को मारा तो औसत डालने का समय लगभग 5,000 / सेकंड हो गया
वैश्विक key_buffer_size = 4294967296 सेट करने से छोटी बाइनरी फ़ाइलों को डालने के लिए गति में थोड़ा सुधार हुआ। नीचे दिया गया ग्राफ विभिन्न नंबरों की पंक्तियों के लिए गति दिखाता है
हालाँकि 1M पंक्तियों को सम्मिलित करने के कारण इसमें प्रदर्शन में सुधार नहीं हुआ।
पंक्तियाँ: 1,000,000 समय: 0: 04: 13.761428 आवेषण / सेकंड: 3,940
एक खाली डेटाबेस के लिए बनाम
पंक्तियाँ: 1,000,000 समय: 0: 00: 6.339295 आवेषण / सेक: 315,492
अपडेट करें
निम्न डेटा बनाम लोड डेटा कमांड का उपयोग करके लोड डेटा करना
SET autocommit=0;
SET foreign_key_checks=0;
SET unique_checks=0;
LOAD DATA INFILE '/mnt/imagesearch/tests/eggs.csv' INTO TABLE test_ClusterMatches;
SET foreign_key_checks=1;
SET unique_checks=1;
COMMIT;
तो यह डेटाबेस आकार के उत्पन्न होने के मामले में काफी आशाजनक लगता है, लेकिन अन्य सेटिंग्स लोड डेटा उल्लंघन कॉल के प्रदर्शन को प्रभावित करने के लिए प्रकट नहीं होती हैं।
मैंने तब विभिन्न मशीनों से कई फाइलें लोड करने की कोशिश की, लेकिन लोड डेटा इनफाइल कमांड टेबल को लॉक कर देता है, फाइलों के बड़े आकार के कारण अन्य मशीनों के साथ समय समाप्त हो जाता है
ERROR 1205 (HY000) at line 1: Lock wait timeout exceeded; try restarting transaction
बाइनरी फ़ाइल में पंक्तियों की संख्या बढ़ाना
rows: 10,000,000 seconds rows: 0:01:36.545094 inserts/sec: 103578.541236
rows: 20,000,000 seconds rows: 0:03:14.230782 inserts/sec: 102970.29026
rows: 30,000,000 seconds rows: 0:05:07.792266 inserts/sec: 97468.3359978
rows: 40,000,000 seconds rows: 0:06:53.465898 inserts/sec: 96743.1659866
rows: 50,000,000 seconds rows: 0:08:48.721011 inserts/sec: 94567.8324859
rows: 60,000,000 seconds rows: 0:10:32.888930 inserts/sec: 94803.3646283
समाधान: ऑटो इंक्रीमेंट का उपयोग करने के बजाय MySQL के बाहर आईडी को प्रीकंप्यूट करना
के साथ तालिका का निर्माण
CREATE TABLE test (
match_index INT UNSIGNED NOT NULL,
cluster_index INT UNSIGNED NOT NULL,
id INT NOT NULL ,
tfidf FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY(cluster_index,match_index,id)
)engine=innodb;
SQL के साथ
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
जैसे ही डेटाबेस आकार में बढ़ता है, स्क्रिप्ट को पूर्व-गणना करने के लिए अनुक्रमणिका प्रदर्शन हिट को हटा देती है।
अद्यतन 2 - मेमोरी टेबल का उपयोग करना
मोटे तौर पर 3 गुना तेजी से, बिना इन-मेमोरी टेबल को डिस्क-आधारित तालिका में स्थानांतरित करने की लागत को ध्यान में रखते हुए।
rows: 0 seconds rows: 0:00:26.661321 inserts/sec: 375075.18851
rows: 10000000 time: 0:00:32.765095 inserts/sec: 305202.83857
rows: 20000000 time: 0:00:38.937946 inserts/sec: 256818.888187
rows: 30000000 time: 0:00:35.170084 inserts/sec: 284332.559456
rows: 40000000 time: 0:00:33.371274 inserts/sec: 299658.922222
rows: 50000000 time: 0:00:39.396904 inserts/sec: 253827.051994
rows: 60000000 time: 0:00:37.719409 inserts/sec: 265115.500617
rows: 70000000 time: 0:00:32.993904 inserts/sec: 303086.291334
rows: 80000000 time: 0:00:33.818471 inserts/sec: 295696.396209
rows: 90000000 time: 0:00:33.534934 inserts/sec: 298196.501594
एक स्मृति आधारित तालिका में डेटा लोड हो रहा है और फिर एक डिस्क आधारित तालिका में कॉपी करके मात्रा में 10 मिनट 59.71 सेकंड का एक ओवरहेड क्वेरी के साथ 107,356,741 पंक्तियां कॉपी करने के लिए किया था
insert into test Select * from test2;
जो 100M पंक्तियों को लोड करने के लिए लगभग 15 मिनट बनाता है, जो लगभग एक डिस्क आधारित तालिका में सीधे डालने के समान है।
id
should be faster. (Although I think you are not looking for this)