Bu soru gelen yayınlanırsa yığın taşması çoğaltma için yorum, özür de bir öneri göre.
Sorular
Soru 1: Veritabanı tablosunun boyutu büyüdükçe, MySQL'i LOAD DATA INFILE çağrısının hızını artırmak için nasıl ayarlayabilirim?
Soru 2: Farklı CSV dosyaları yüklemek, performansı artırmak veya öldürmek için bir bilgisayar kümesi kullanmak mı istiyorsunuz? (bu, yük verilerini ve toplu ekleri kullanarak yarınki tezgah işaretleme görevim)
Hedef
Görsel arama için farklı özellik dedektörleri ve kümeleme parametreleri kombinasyonlarını deniyoruz, sonuç olarak zamanında ve büyük veritabanları oluşturmamız gerekiyor.
Makine Bilgisi
Makinenin 256 gig ram'si var ve veritabanını dağıtarak oluşturma süresini iyileştirmenin bir yolu varsa aynı miktarda ram ile başka 2 makine daha mevcut mu?
Tablo Şeması
tablo şeması benziyor
+---------------+------------------+------+-----+---------+----------------+
| 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 | |
+---------------+------------------+------+-----+---------+----------------+
ile yaratıldı
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;
Kıyaslama
İlk adım, toplu ekleri ve ikili dosyadan boş bir tabloya yüklemeyi karşılaştırmaktı.
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
Performanstaki fark göz önüne alındığında, ikili bir csv dosyasından veri yükleme ile gitti, önce aşağıdaki çağrıyı kullanarak 100K, 1M, 20M, 200M satırları içeren ikili dosyaları yükledim.
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test;
200M satır ikili dosyası (~ 3GB csv dosyası) yükünü 2 saat sonra öldürdüm.
Bu yüzden tablo oluşturmak için bir komut dosyası çalıştırdım ve bir ikili dosyadan farklı sayıda satır ekledikten sonra tabloyu bırakın, aşağıdaki grafiğe bakın.
İkili dosyadan 1M satır eklemek yaklaşık 7 saniye sürdü. Daha sonra, belirli bir veritabanı boyutunda bir darboğaz olup olmayacağını görmek için bir seferde 1M satırları ekleyerek karşılaştırmaya karar verdim. Veritabanı yaklaşık 59 milyon satıra çarptığında ortalama ekleme süresi yaklaşık 5.000 / saniyeye düştü
Genel key_buffer_size = 4294967296 değeri ayarlandığında, daha küçük ikili dosyalar eklemek için hızlar biraz artırıldı. Aşağıdaki grafik farklı satır sayılarının hızlarını göstermektedir
Ancak 1M satırları eklemek için performansı iyileştirmedi.
satır sayısı: 1.000.000 süre: 0: 04: 13.761428 kesici uçlar / sn: 3.940
vs boş bir veritabanı için
satır sayısı: 1.000.000 süre: 0: 00: 6.339295 kesici uçlar / sn: 315.492
Güncelleme
Aşağıdaki verileri kullanarak yükleme verisini yapmak - sadece yükle veri komutunu kullanmak yerine
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;
Bu nedenle, oluşturulan veritabanı boyutu açısından oldukça ümit verici görünüyor, ancak diğer ayarlar yük verileri dosya aramasının performansını etkilemiyor gibi görünüyor.
Daha sonra farklı makinelerden birden fazla dosya yüklemeyi denedim ancak veri yükleme komutu, diğer makinelerin zaman aşımına uğramasına neden olan dosyaların büyük boyutu nedeniyle tabloyu kilitliyor
ERROR 1205 (HY000) at line 1: Lock wait timeout exceeded; try restarting transaction
İkili dosyadaki satır sayısını artırma
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
Çözüm: Otomatik artış kullanmak yerine kimliği MySQL dışında önceden hesaplama
Masayı oluşturmak
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 ile
LOAD DATA INFILE '/mnt/tests/data.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
Komut dosyasının dizinleri önceden hesaplamasını sağlamak, veritabanı büyüdükçe performans isabeti kaldırmış gibi görünüyor.
Güncelleme 2 - Bellek tablolarını kullanma
Bellek içi bir tabloyu disk tabanlı tabloya taşıma maliyeti hesaba katılmadan yaklaşık 3 kat daha hızlı.
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
verileri bir bellek tabanlı tabloya yükleyerek ve sonra parçalar halinde bir disk tabanlı tabloya kopyalayarak 107.356.741 satır sorgu ile kopyalamak için 10 dakika 59.71 sn genel gider vardı
insert into test Select * from test2;
100M satırlarının yüklenmesini yaklaşık 15 dakika yapar, bu da doğrudan disk tabanlı bir tabloya yerleştirmekle aynıdır.
id
daha hızlı değiştirmek gerektiğini düşünüyorum. (Bunu aradığınızı düşünmeme rağmen)