Câu hỏi này được đăng lại từ Stack Overflow dựa trên một gợi ý trong các bình luận, lời xin lỗi cho sự trùng lặp.
Câu hỏi
Câu hỏi 1: khi kích thước của bảng cơ sở dữ liệu lớn hơn, làm cách nào tôi có thể điều chỉnh MySQL để tăng tốc độ của cuộc gọi LOAD DATA INFILE?
Câu hỏi 2: sử dụng một cụm máy tính để tải các tệp csv khác nhau, cải thiện hiệu suất hoặc tiêu diệt nó? (đây là nhiệm vụ đánh dấu băng ghế của tôi cho ngày mai bằng cách sử dụng dữ liệu tải và chèn số lượng lớn)
Mục tiêu
Chúng tôi đang thử các kết hợp khác nhau của các trình phát hiện tính năng và các tham số phân cụm để tìm kiếm hình ảnh, do đó chúng tôi cần có khả năng xây dựng và cơ sở dữ liệu lớn một cách kịp thời.
Thông tin máy móc
Máy có 256 gig ram và có 2 máy khác có sẵn với cùng một lượng ram nếu có cách nào để cải thiện thời gian tạo bằng cách phân phối cơ sở dữ liệu?
Lược đồ bảng
lược đồ bảng trông giống như
+---------------+------------------+------+-----+---------+----------------+
| 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 | |
+---------------+------------------+------+-----+---------+----------------+
được tạo nên bởi
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;
Điểm chuẩn cho đến nay
Bước đầu tiên là so sánh các phần chèn hàng loạt với việc tải từ tệp nhị phân vào một bảng trống.
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
Do sự khác biệt về hiệu suất mà tôi đã thực hiện với việc tải dữ liệu từ tệp csv nhị phân, đầu tiên tôi đã tải các tệp nhị phân chứa các hàng 100K, 1M, 20M, 200M bằng cách sử dụng cuộc gọi bên dưới.
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
Tôi đã giết tệp nhị phân hàng 200M (~ 3GB tệp csv) sau 2 giờ.
Vì vậy, tôi đã chạy một kịch bản để tạo bảng và chèn số lượng hàng khác nhau từ tệp nhị phân rồi thả bảng, xem biểu đồ bên dưới.
Mất khoảng 7 giây để chèn 1M hàng từ tệp nhị phân. Tiếp theo, tôi quyết định điểm chuẩn chèn các hàng 1M tại một thời điểm để xem liệu sẽ có một nút cổ chai ở kích thước cơ sở dữ liệu cụ thể. Khi Cơ sở dữ liệu đạt khoảng 59 triệu hàng, thời gian chèn trung bình giảm xuống khoảng 5.000 / giây
Đặt key_buffer_size = 4294967296 toàn cầu đã cải thiện tốc độ một chút để chèn các tệp nhị phân nhỏ hơn. Biểu đồ bên dưới hiển thị tốc độ cho các số hàng khác nhau
Tuy nhiên, để chèn các hàng 1M, nó không cải thiện hiệu suất.
hàng: 1.000.000 thời gian: 0: 04: 13.761428 chèn / giây: 3.940
so với cơ sở dữ liệu trống
hàng: 1.000.000 thời gian: 0: 00: 6.339295 chèn / giây: 315,492
Cập nhật
Thực hiện tải dữ liệu bằng cách sử dụng trình tự sau so với chỉ sử dụng lệnh tải dữ liệu
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;
Vì vậy, điều này có vẻ khá hứa hẹn về kích thước cơ sở dữ liệu đang được tạo nhưng các cài đặt khác dường như không ảnh hưởng đến hiệu suất của cuộc gọi tải dữ liệu tải.
Sau đó tôi đã thử tải nhiều tệp từ các máy khác nhau nhưng lệnh tải dữ liệu tải dữ liệu khóa bảng, do kích thước lớn của các tệp khiến các máy khác hết thời gian với
ERROR 1205 (HY000) at line 1: Lock wait timeout exceeded; try restarting transaction
Tăng số lượng hàng trong tệp nhị phân
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
Giải pháp: Tính toán trước id bên ngoài MySQL thay vì sử dụng tự động tăng
Xây dựng bảng với
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;
với SQL
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
Bắt tập lệnh để tính toán trước các chỉ mục dường như đã loại bỏ hiệu năng nhấn khi cơ sở dữ liệu tăng kích thước.
Cập nhật 2 - sử dụng bảng nhớ
Nhanh hơn gấp 3 lần, mà không tính đến chi phí di chuyển một bảng trong bộ nhớ sang bảng dựa trên đĩa.
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
bằng cách tải dữ liệu vào một bảng dựa trên bộ nhớ và sau đó sao chép nó vào một bảng dựa trên đĩa trong một khối có thời gian hoạt động là 10 phút 59,71 giây để sao chép 107.356.741 hàng với truy vấn
insert into test Select * from test2;
làm cho nó mất khoảng 15 phút để tải 100M hàng, tương đương với việc chèn trực tiếp vào bảng dựa trên đĩa.
id
nên nhanh hơn. (Mặc dù tôi nghĩ rằng bạn không tìm kiếm điều này)