mysqldump'tan yavaş veri yükleme hızı


21

Bazıları 10 milyon, bazıları 100 milyon olan yaklaşık 30 tablodan oluşan, orta boyutta bir MySQL veri tabanına sahibim. mysqldump(Ayrı dosyalar halinde) tüm tabloları oldukça hızlıdır belki 20 dakika sürer. Yaklaşık 15GB veri üretir. En büyük dökümlü dosyalar 2GB aralığındadır.

Verileri başka bir kutuya, altı çekirdekli, 8 GB'lik bir makineye MySQL'e yüklediğimde, sonsuza dek sürüyor. Kolayca 12 saat veya daha fazla saat.

Dosyayı yüklemek için sadece mysql istemcisini çalıştırıyorum.

mysql database < footable.sql

doğrudan dosya ile doğrudan mysqldump dışında

mysqldump database foo > footable.sql

Açıkçası yanlış bir şey yapıyorum. Nereden başlayacağım ki makul bir sürede bitirebilirim?

Çöpte veya yükte hiçbir anahtar kullanmıyorum.


Ayrıca, çöplüğün yükü sırasında ikili günlük kaydını devre dışı
bırakabilirsiniz

Yanıtlar:


22

Çöp üretme ve geri yükleme işleminde size yardımcı olabilecekleri bazı noktaları göz önünde bulundurun.

  1. Extended insertsÇöplüklerde kullanın .
  2. Daha hızlı olan --tabkullanabilmeniz için formatla döküm yapın .mysqlimportmysql < dumpfile
  3. Her tablo için bir tane olmak üzere birden fazla iş parçacığı ile içe aktarın.
  4. Mümkünse farklı bir veritabanı motoru kullanın. innodb gibi ağır işlem gerektiren bir motora aktarma işlemi oldukça yavaştır. MyISAM gibi işlemsel olmayan bir motora eklemek çok daha hızlıdır.
  5. Yabancı anahtar kontrollerini kapatın ve otomatik onaylamayı açın.
  6. Innodb'a içe aktarıyorsanız, yapabileceğiniz en etkili şey innodb_flush_log_at_trx_commit = 2, içe aktarma çalışırken geçici olarak my.cnf'nize koymaktır . ACID'ye ihtiyacınız varsa 1'e geri koyabilirsiniz

Bir şans ver..


Senin ipucun innodb_flush_log_at_trx_commit = 2benim günümü kurtardı. 600 MB'lık bir dökümü içe aktarmak (tek bir büyük işlem olarak) 6 saate ihtiyaç duyardı, ancak bu geçici ayarla 30 dakika içinde tamamlandı!
Daniel Marschall

1
İstediğiniz şeyleri 'enter' tuşuna bastıktan 4 gün sonra 80 gig veri tabanını bir çöplükten yüklemeye çalışmadan önce bilmeniz gerekenler ... :)
Dmitri DB

7

Abdul'in cevabına ek olarak , --disable-keystüm veriler bir tablo için yüklenene kadar anahtarları kapatan seçeneğin önemini vurgulamak istiyorum . Bu seçenek, --optvarsayılan olarak etkin olan ve işaret etmenin önemli olduğunu düşündüğü açma / kapama düğmesinin bir parçası olarak etkindir.

Ekler sırasında tuşları atlamazsanız, eklenen her satır dizini yeniden oluşturur. Son derece yavaş bir işlem.


- disable-keys, mysqldump öğesinin bir parçası mı? veya yeniden yükle?
Pat Farrell

döküm dosyasına eklenecek
Derek Downey

--optvarsayılan olarak
açıktır

1
This option is effective only for nonunique indexes of MyISAM tables. It has no effect for other tables
Ethan Allen

7

Son zamanlarda bununla çok uğraşıyorum. İthalatları paralel olarak yaparak ithalat performansını kesinlikle artırabilirsiniz. Yavaşlamanın çoğu G / Ç'ye dayanıyor, ancak tablolara döküp% 4'lük bir artış göstererek hala% 40 iyileşme sağlayabiliyorsunuz.

Bunu şu şekilde xargs ile yapabilirsiniz:

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

Dosyaların mysql'ye gönderilmeden önce sıkıştırılması, indirgenmiş G / Ç nedeniyle çoğunlukla hiçbir şeyi yavaşlatmaz. Tablolarım yaklaşık 10: 1'e kadar sıkıştırıldı, bu yüzden çok fazla disk alanı kazandırıyor.

4 çekirdekli makinelerde, 4 işlemi kullanmanın optimal olduğunu, ancak 3'ü kullanmaktan ancak marjinal olarak daha iyi olduğunu gördüm.

Dikkat edilecek başka şeyler var. 4k sektör sürücünüz varsa key_cache_block_size=4096ve sahip olduğunuzdan emin olun myisam_block_size=4K.

MyISAM tablolarını kullanıyorsanız, myisam_repair_threads = 2veya daha yukarısını ayarlayın . Bu, fazladan çekirdeklerinizin dizinleri yeniden oluşturmasına yardımcı olur.

Hiç değişmediğinizden emin olun. Öyleyse, boyutunu küçültün innodb_buffer_pool_size.

Sanırım bu seçenekler arasında innnodb ile biraz hız kazandım:

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(son üçünde kapsamlı test yapmadım - sanırım onları internette öneri olarak buldum.) innodb_flush_log_at_commit=0MySQL'in çökmesi ya da gücünün kesilmesiyle bozulmaya yol açabileceğini unutmayın .


Greg, siteye hoş geldin ve cevabın için teşekkür ederim. *_block_sizeVe konusundaki önerileriniz için bazı kaynaklar veya sebepler sunabilir misiniz myisam_repair_threads? Ayrıca, 'internetteki önerileri' temel alarak değişkenleri ayarlamak için tavsiye vermemiz gerektiğinden de emin değiliz :)
Derek Downey

5

Genelde MyISAM tablolarınız varsa, toplu ekleme arabelleğini arttırmalısınız . İşte MySQL Belgeleri bulk_insert_buffer_size ayarında ne diyor :

MyISAM, INSERT ... SELECT, INSERT ... DEĞERLER (...), (...), ... ve LOAD DATA INFILE için toplu eklemeleri daha hızlı yapmak için ağaç benzeri özel bir önbellek kullanır tablolar. Bu değişken, önbellek ağacının boyutunu, iş parçacığı başına bayt cinsinden sınırlar. 0'a ayarlamak bu optimizasyonu devre dışı bırakır. Varsayılan değer 8 MB'dir.

Yapmanız gereken iki şey var.

1) /etc/my.cnf dosyasına ekleyin.

[mysqld]
bulk_insert_buffer_size=512M

2) Bunun için global değeri ayarlayın

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

Genel olarak bulk_insert_buffer_size öğesini ayarlama izniniz yoksa, bunu yapın

service mysql restart

Tabii ki, bu InnoDB için değil.

Başka bir açıdan, tabloların InnoDB veya MyISAM olup olmadığı, dizinler tablodan daha büyükse, çok fazla dizininiz olabilir. Genelde, bir MyISAM mysqldump dosyasının yeniden yüklenmesinin, mysqldump'in yaptığı süre boyunca 3 kez sürmesi gerektiğini düşünüyorum. Ayrıca, bir InnoDB mysqldump'ın yeniden yüklenmesinin, mysqldump'in yaptığı süre boyunca 4 kez sürmesi gerektiğini düşünüyorum.

Bir mysqldump'ı yeniden yüklemek için 4: 1 oranını aşıyorsanız, kesinlikle iki problemden birine sahipsiniz:

  • çok fazla dizin var
  • büyük sütunlar nedeniyle dizinler çok büyük

Verilerinizin boyutunu bu şekilde depolama motoruyla ölçebilirsiniz:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

Dizinlerin neredeyse veri kadar büyük veya daha büyük olup olmadığına bakın

İkili günlük kaydını bu şekilde devre dışı bırakmayı da düşünebilirsiniz:

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

komut dosyasını yeniden yüklemeden önce


Günümü kaç kere kurtardığınızı bilmiyorum ama kesinlikle çok oldu
Dmitri DB

2

Dosya sistemini tamamen atlar ve sadece mysqldump çıktısını doğrudan bir MySQL işlemine geçirirseniz, gözle görülür performans iyileştirmeleri görmeniz gerekir. Nihayetinde kullandığınız disk sürücünün türüne ne kadar bağlıdır, ancak tek başına bu nedenle veritabanı boyutuna bakılmaksızın artık döküm dosyalarını nadiren kullanıyorum.

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy

1

Deneyimlerime göre, sabit disk tıkanıklığı. Dönen diskleri unutun. SSD daha iyidir, ancak bugüne kadar en iyisi bunu RAM’de gerçekleştirmektir - veri tabanının tamamını kısa bir süre tutacak kadar varsa. Kabaca:

  1. MySQL'i durdur
  2. / var / lib / mysql içeriğini uzaklaştır
  3. boş bir / var / lib / mysql dir oluşturun
  4. mount -t tmpfs -o boyutu = 32g tmpfs / var / lib / mysql (boyutu ayarla)
  5. boş bir db oluşturun (örneğin, mysql_install_db veya önceki içerikleri geri yükleyin)
  6. mysqld'i başlat
  7. ithalat
  8. MySQL'i durdur
  9. kopyalamak / var / lib / mysql - mysql2
  10. mysql umount; rmdir mysql
  11. mysql2'yi mysql'ye taşı
  12. MySQL'e başla, mutlu ol

Benim için, ~ 10G (/ var / lib / mysql tüketen ~ 20G) dökümü yaklaşık 35 dakika (mydumper / myloader), 45 dakika (mysqldump - tab / mysqlimport), 50 dakika (mysqldump / mysql) içine alınabilir. , 2x6 çekirdekli bir 3.2GHz Xeon'da.

Tek bir makinede yeterli RAM'iniz yoksa, ancak hızlı ağa sahip yan yana birkaç bilgisayarınız varsa, RAM'lerinin nbd (ağ blok cihazı) ile birleştirilip birleştirilemeyeceğini görmek ilginç olacaktır. Veya innodb_file_per_table ile yukarıdaki tabloyu her tablo için tekrarlayabilirsiniz.


Merakım dışında 2 GB veri tabanı için SSD (SSDSC2BB48) ile karşılaştırmak için mysql datadir'i RAM'e kaydetmeyi denedim. Sonuçlar KİMLİK idi, her ikisi de 207-209 saniye sürdü. MySQL'i başlatmanız / durdurmanız ve dizinleri kopyalamanız gerektiği gerçeğini göz önünde bulundurarak, SSD yerine bir RAM disk kullanarak benim durumumda çok daha yavaştı
Shocker

Bu size yaklaşık 3-4 dakika sürerse, bu konuyla ilgili olandan çok daha küçük bir veritabanınız olduğunu sanırım. Benzer şekilde büyük veritabanlarıyla olan deneyimlerinizi, bu konuda belirtilenlerden daha fazla duymak ilginç olurdu.
egmont
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.