Pertanyaan ini diposting ulang dari Stack Overflow berdasarkan saran di komentar, permintaan maaf untuk duplikasi.
Pertanyaan
Pertanyaan 1: saat ukuran tabel basis data semakin besar, bagaimana saya bisa menyetel MySQL untuk meningkatkan kecepatan panggilan LOAD DATA INFILE?
Pertanyaan 2: apakah akan menggunakan sekelompok komputer untuk memuat file csv yang berbeda, meningkatkan kinerja atau membunuhnya? (ini adalah tugas menandai bangku saya untuk besok menggunakan data muatan dan sisipan massal)
Tujuan
Kami mencoba kombinasi berbeda dari pendeteksi fitur dan parameter pengelompokan untuk pencarian gambar, sebagai akibatnya kami harus dapat membangun dan database besar secara tepat waktu.
Info Mesin
Mesin memiliki 256 gig ram dan ada 2 mesin lain yang tersedia dengan jumlah ram yang sama jika ada cara untuk meningkatkan waktu pembuatan dengan mendistribusikan database?
Skema Tabel
skema tabel terlihat seperti
+---------------+------------------+------+-----+---------+----------------+
| 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 | |
+---------------+------------------+------+-----+---------+----------------+
dibuat dengan
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;
Benchmarking sejauh ini
Langkah pertama adalah membandingkan sisipan massal vs memuat dari file biner ke tabel kosong.
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
Mengingat perbedaan dalam kinerja saya telah pergi dengan memuat data dari file csv biner, pertama saya memuat file biner yang berisi 100K, 1M, 20M, 200M baris menggunakan panggilan di bawah ini.
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
Saya membunuh file biner baris 200M (~ file csv 3GB) dimuat setelah 2 jam.
Jadi saya menjalankan skrip untuk membuat tabel, dan memasukkan nomor baris yang berbeda dari file biner kemudian menjatuhkan tabel, lihat grafik di bawah ini.
Butuh sekitar 7 detik untuk menyisipkan baris 1M dari file biner. Selanjutnya saya memutuskan untuk benchmark memasukkan 1M baris sekaligus untuk melihat apakah akan ada hambatan pada ukuran database tertentu. Setelah Database mencapai sekitar 59M baris, waktu memasukkan rata-rata turun menjadi sekitar 5.000 / detik
Mengatur key_buffer_size global = 4294967296 meningkatkan kecepatan sedikit untuk memasukkan file biner yang lebih kecil. Grafik di bawah ini menunjukkan kecepatan untuk jumlah baris yang berbeda
Namun untuk memasukkan baris 1M itu tidak meningkatkan kinerja.
baris: 1.000.000 waktu: 0: 04: 13.761428 sisipan / detik: 3.940
vs untuk database kosong
baris: 1.000.000 waktu: 0: 00: 6.339295 sisipan / detik: 315.492
Memperbarui
Melakukan memuat data menggunakan urutan berikut vs hanya menggunakan perintah memuat data
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;
Jadi ini terlihat cukup menjanjikan dalam hal ukuran basis data yang sedang dibuat tetapi pengaturan lain tampaknya tidak mempengaruhi kinerja panggilan infil data beban.
Saya kemudian mencoba memuat beberapa file dari mesin yang berbeda tetapi perintah memuat data infile mengunci tabel, karena ukuran file yang besar menyebabkan mesin lain kehabisan waktu dengan
ERROR 1205 (HY000) at line 1: Lock wait timeout exceeded; try restarting transaction
Meningkatkan jumlah baris dalam file biner
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
Solusi: Precomputing id di luar MySQL alih-alih menggunakan penambahan otomatis
Membangun meja dengan
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;
dengan SQL
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
Membuat skrip untuk melakukan pre-compute indeks tampaknya telah menghapus hit kinerja sebagai database tumbuh dalam ukuran.
Perbarui 2 - menggunakan tabel memori
Secara kasar 3 kali lebih cepat, tanpa memperhitungkan biaya memindahkan tabel di-memori ke meja berbasis disk.
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
dengan memuat data ke dalam tabel berbasis memori dan kemudian menyalinnya ke meja berbasis disk dalam potongan memiliki overhead 10 menit 59,71 detik untuk menyalin 107.356.741 baris dengan kueri
insert into test Select * from test2;
yang membuatnya sekitar 15 menit untuk memuat 100M baris, yang kira-kira sama dengan langsung memasukkannya ke dalam tabel berbasis disk.
id
menjadi lebih cepat. (Meskipun saya pikir Anda tidak mencari ini)