it-swarm.asia

kecepatan memuat data yang lambat dari mysqldump

Saya punya database MySQL ukuran sedang dengan sekitar 30 tabel, beberapa di antaranya adalah 10 juta catatan, beberapa 100 juta. mysqldump dari semua tabel (ke file terpisah) cukup cepat, mungkin membutuhkan waktu 20 menit. Ini menghasilkan sekitar 15GB data. File yang dibuang terbesar berada dalam kisaran 2GB.

Ketika saya memuat data ke dalam MySQL di kotak lain, mesin enam-inti, 8GB, dibutuhkan selamanya. Mudah 12 jam jam atau lebih.

Saya hanya menjalankan klien mysql untuk memuat file, mis.

mysql database < footable.sql

langsung dengan file langsung keluar dari mysqldump

mysqldump database foo > footable.sql

Jelas saya melakukan sesuatu yang salah. Di mana saya memulai sehingga bisa selesai dalam waktu yang wajar?

Saya tidak menggunakan tombol apa pun pada dump atau beban.

21
Pat Farrell

Ambil beberapa poin ini dalam pertimbangan Anda, mereka dapat membantu Anda dalam hal menghasilkan dump dan mengembalikannya.

  1. Gunakan Extended inserts dalam kesedihan.
  2. Buang dengan --tab format sehingga Anda dapat menggunakan mysqlimport, yang lebih cepat dari mysql < dumpfile.
  3. Impor dengan beberapa utas, satu untuk setiap tabel.
  4. Gunakan mesin database yang berbeda jika memungkinkan. mengimpor ke mesin yang sangat transaksional seperti innodb sangat lambat. Memasukkan ke mesin non-transaksional seperti MyISAM jauh lebih cepat.
  5. Matikan cek kunci asing dan aktifkan komit otomatis.
  6. Jika Anda mengimpor ke innodb, satu-satunya hal paling efektif yang dapat Anda lakukan adalah meletakkan innodb_flush_log_at_trx_commit = 2 di my.cnf Anda, untuk sementara saat impor berjalan. Anda dapat mengembalikannya ke 1 jika Anda memerlukan ASAM

Cobalah..

22
Abdul Manaf

Saya telah banyak berurusan dengan ini belakangan ini. Anda pasti dapat meningkatkan kinerja impor dengan melakukan impor secara paralel. Sebagian besar perlambatan berbasis I/O, tetapi Anda masih bisa mendapatkan peningkatan 40% dengan membuang ke dalam tabel dan kemudian mengimpornya mengatakan 4 pada suatu waktu.

Anda dapat melakukan ini dengan xargs seperti ini:

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

memiliki file yang di-gzip sebelum mendorongnya ke mysql tidak memperlambat apa pun terutama karena I/O yang diturunkan. Meja saya dikompresi hingga sekitar 10: 1, sehingga menghemat banyak ruang disk.

Saya telah menemukan bahwa pada 4 mesin inti, menggunakan 4 proses adalah optimal, meskipun hanya sedikit lebih baik daripada menggunakan 3. Jika Anda memiliki SSD atau RAID cepat, Anda mungkin akan skala yang lebih baik.

Beberapa hal lain yang perlu diperhatikan. Jika Anda memiliki drive sektor 4k, pastikan Anda memiliki key_cache_block_size=4096 dan myisam_block_size=4K.

Jika Anda menggunakan tabel MyISAM, atur myisam_repair_threads = 2 atau lebih tinggi. Ini akan memungkinkan core tambahan Anda untuk membantu membangun kembali indeks.

Pastikan Anda tidak bertukar sama sekali. Jika ya, kurangi ukuran innodb_buffer_pool_size.

Saya pikir saya mendapat beberapa speedup dengan innnodb dengan opsi ini juga:

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

(tiga terakhir saya tidak menguji secara luas - saya pikir saya menemukan mereka sebagai saran di internet.) Perhatikan bahwa innodb_flush_log_at_commit=0 dapat menyebabkan korupsi dengan mysql crash atau power padam.

7
greg

Selain jawaban Abdul , saya ingin menekankan pentingnya --disable-keys opsi, yang mematikan kunci sampai semua data dimuat untuk sebuah tabel. Opsi ini diaktifkan sebagai bagian dari --opt toggle, yang diaktifkan secara default, tetapi menganggapnya penting untuk ditunjukkan.

Jika Anda tidak melewatkan kunci selama sisipan, maka setiap baris yang dimasukkan akan membangun kembali indeks. Proses yang sangat lambat.

7
Derek Downey

Jika Anda terutama memiliki tabel MyISAM, Anda harus menambah buffer penyisipan massal . Inilah yang dikatakan Dokumentasi MySQL tentang pengaturan bulk_insert_buffer_size :

MyISAM menggunakan cache mirip pohon untuk membuat sisipan massal lebih cepat untuk INSERT ... SELECT, INSERT ... VALUES (...), (...), ..., dan LOAD DATA INFILE saat menambahkan data ke nonempty meja. Variabel ini membatasi ukuran pohon cache dalam byte per utas. Menetapkannya ke 0 menonaktifkan pengoptimalan ini. Nilai default adalah 8MB.

Ada dua hal yang perlu Anda lakukan

1) Tambahkan ke /etc/my.cnf

[mysqld]
bulk_insert_buffer_size=512M

2) Tetapkan nilai global untuk itu

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

Jika Anda tidak memiliki hak istimewa untuk mengatur bulk_insert_buffer_size secara global, maka lakukan ini

service mysql restart

Tentu saja, ini bukan untuk InnoDB.

Dari sudut lain, apakah tabelnya InnoDB atau MyISAM, jika indeks lebih besar dari tabel, Anda mungkin memiliki terlalu banyak indeks. Saya biasanya merasa bahwa pemuatan ulang myISAM mysqldump akan memakan waktu 3 kali selama mysqldump diperlukan. Saya juga memberi tahu bahwa memuat ulang mysqldump InnoDB harus memakan waktu 4 kali lipat selama mysqldump dibuat.

Jika Anda melebihi rasio 4: 1 untuk memuat ulang mysqldump, Anda pasti memiliki satu dari dua masalah:

  • terlalu banyak indeks
  • indeks terlalu besar karena kolom besar

Anda dapat mengukur ukuran data Anda dengan mesin penyimpanan dengan ini:

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;

Lihat apakah indeks hampir sebesar data atau bahkan lebih besar

Anda juga dapat mempertimbangkan menonaktifkan pencatatan biner seperti ini:

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

sebelum memuat ulang skrip

5
RolandoMySQLDBA

Jika Anda mem-bypass sistem file sama sekali dan hanya menyalurkan output mysqldump langsung ke proses MySQL, Anda akan melihat peningkatan kinerja yang nyata. Seberapa besar akhirnya tergantung pada jenis disk drive yang Anda gunakan, tetapi saya jarang menggunakan file dump lagi terlepas dari ukuran database karena alasan ini saja.

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

Menurut pengalaman saya, hard drive adalah hambatannya. Lupakan disk yang berputar. SSD lebih baik, tetapi sejauh ini yang terbaik adalah melakukan ini di RAM - jika Anda memiliki cukup untuk menahan seluruh basis data untuk sementara waktu.)

  1. hentikan mysqld
  2. memindahkan isi/var/lib/mysql yang sudah ada
  3. buat dir/var/lib/mysql dir yang kosong
  4. mount -t tmpfs -o size = 32g tmpfs/var/lib/mysql (sesuaikan ukurannya)
  5. buat db kosong (mis. mysql_install_db, atau pulihkan konten sebelumnya)
  6. mulai mysqld
  7. impor
  8. hentikan mysqld
  9. salin/var/lib/mysql ke mysql2
  10. umount mysql; rmdir mysql
  11. pindahkan mysql2 ke mysql
  12. mulai mysqld, senanglah

Bagi saya, dump ~ 10G (/ var/lib/mysql mengkonsumsi ~ 20G) dapat diimpor dalam waktu sekitar 35 menit (mydumper/myloader), 45 menit (mysqldump --tab/mysqlimport), 50 menit (mysqldump/mysql) , pada Xeon 2x6-core 3.2GHz.

Jika Anda tidak memiliki cukup RAM dalam satu mesin, tetapi memiliki beberapa komputer yang bersebelahan dengan jaringan cepat, akan menarik untuk melihat apakah RAM mereka dapat bergabung dengan nbd (jaringan) blokir perangkat) Atau, dengan innodb_file_per_table, Anda mungkin dapat mengulangi proses di atas untuk setiap tabel.

1
egmont