คำถามนี้ถูกโพสต์ใหม่จากStack Overflowตามคำแนะนำในความคิดเห็นขอโทษสำหรับการทำซ้ำ
คำถาม
คำถามที่ 1: เนื่องจากขนาดของตารางฐานข้อมูลมีขนาดใหญ่ขึ้นฉันจะปรับแต่ง MySQL เพื่อเพิ่มความเร็วของการโทรโหลดข้อมูล INFILE ได้อย่างไร
คำถามที่ 2: จะใช้กลุ่มคอมพิวเตอร์เพื่อโหลดไฟล์ csv ที่แตกต่างกันปรับปรุงประสิทธิภาพหรือทำลายไฟล์หรือไม่ (นี่คือภารกิจการทำเครื่องหมายของฉันสำหรับวันพรุ่งนี้โดยใช้ข้อมูลโหลดและเม็ดมีดจำนวนมาก)
เป้าหมาย
เรากำลังลองใช้ชุดตรวจจับคุณสมบัติและพารามิเตอร์การจัดกลุ่มที่แตกต่างกันสำหรับการค้นหารูปภาพดังนั้นเราจึงจำเป็นต้องสามารถสร้างและฐานข้อมูลขนาดใหญ่ได้ในเวลาที่เหมาะสม
ข้อมูลเครื่อง
เครื่องมี ram ขนาด 256 กิ๊กและมีอีก 2 เครื่องที่มี ram เท่ากันถ้ามีวิธีในการปรับปรุงเวลาการสร้างโดยการกระจายฐานข้อมูลหรือไม่?
สคีมาตาราง
คีมาตารางดูเหมือน
+---------------+------------------+------+-----+---------+----------------+
| 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
ด้วยความแตกต่างของประสิทธิภาพที่ฉันได้ไปกับการโหลดข้อมูลจากไฟล์ไบนารี csv ก่อนอื่นฉันโหลดไฟล์ไบนารีที่มี 100K, 1M, 20M, 200M แถวโดยใช้การโทรด้านล่าง
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
ฉันฆ่าโหลดไบนารีไฟล์ 200M แถว (~ 3GB csv) โหลดหลังจาก 2 ชั่วโมง
ดังนั้นฉันจึงรันสคริปต์เพื่อสร้างตารางและแทรกจำนวนแถวที่แตกต่างจากไฟล์ไบนารีจากนั้นให้วางตารางดูกราฟด้านล่าง
ใช้เวลาประมาณ 7 วินาทีในการแทรก 1M แถวจากไฟล์ไบนารี ต่อไปฉันตัดสินใจสร้างเกณฑ์มาตรฐานการแทรกแถว 1M ในเวลาเพื่อดูว่าจะมีคอขวดที่ขนาดฐานข้อมูลที่เฉพาะเจาะจง เมื่อฐานข้อมูลไปถึงแถวประมาณ 59M เวลาแทรกเฉลี่ยลดลงไปประมาณ 5,000 / วินาที
การตั้งค่า global key_buffer_size = 4294967296 ปรับปรุงความเร็วเล็กน้อยสำหรับการแทรกไฟล์ไบนารีขนาดเล็กลง กราฟด้านล่างแสดงความเร็วสำหรับจำนวนแถวที่แตกต่างกัน
อย่างไรก็ตามสำหรับการแทรก 1M แถวมันไม่ได้ปรับปรุงประสิทธิภาพ
แถว: 1,000,000 เวลา: 0: 04: 13.761428 ส่วนแทรก / วินาที: 3,940
vs สำหรับฐานข้อมูลเปล่า
แถว: 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;
ดังนั้นสิ่งนี้จึงมีแนวโน้มที่ค่อนข้างสดใสในแง่ของขนาดฐานข้อมูลที่ถูกสร้างขึ้น แต่การตั้งค่าอื่น ๆ จะไม่ส่งผลต่อประสิทธิภาพของการเรียก infile data ของโหลด
ฉันพยายามโหลดหลายไฟล์จากเครื่องที่แตกต่างกัน แต่คำสั่งโหลดข้อมูล infile ล็อคตารางเนื่องจากไฟล์มีขนาดใหญ่ทำให้เครื่องอื่นหมดเวลา
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;
ซึ่งใช้เวลาประมาณ 15 นาทีในการโหลดแถว 100M ซึ่งจะประมาณเดียวกับการแทรกลงในตารางที่อิงกับดิสก์โดยตรง
id
ควรเร็วขึ้น (แม้ว่าฉันคิดว่าคุณไม่ได้มองหาสิ่งนี้)