Penyisipan InnoDB lebih cepat

8

Saya seorang siswa sekolah menengah yang meneliti OLAP dengan Mondrian OLAP. Jadi saya ingin memasukkan data ke InnoDB (MySQL 5.5) lebih cepat pada pemuatan awal. Dalam lingkungan ini, satu-satunya pengguna adalah saya, jadi saya pikir dapat memungkinkan pengaturan yang lebih longgar untuk kecepatan penyisipan. Saat ini, saya menggunakan teknik berikut.

  • nonaktifkan log_bin
  • memungkinkan skip-innodb-doublewrite
  • setel transaction_isolationke READ-COMMITTEDatau READ-UNCOMMITTED(sebenarnya READ-COMMITED)
  • setel innodb_flush_log_at_trx_commitke 0atau 2(sebenarnya 0)
  • diatur innodb_buffer_pool_sizeke 5GB (sistem memiliki 6GB RAM)

Apakah ada teknik lain untuk penyisipan yang lebih cepat di InnoDB? Dan apakah saya harus memodifikasi innodb_io_read_threaddan innodb_io_write_thread? Jika Anda membutuhkan informasi lebih lanjut, tolong beri tahu saya.

inohiro
sumber

Jawaban:

9

SARAN # 1

Jika mesin Anda memiliki beberapa inti, Anda perlu menambah yang berikut:

[mysqld]
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000

Apa ini?

  • innodb_read_io_threads - Jumlah utas I / O untuk operasi baca di InnoDB.
  • innodb_write_io_threads - Jumlah utas I / O untuk operasi penulisan di InnoDB.
  • innodb_io_capacity - Batas atas aktivitas I / O yang dilakukan oleh tugas latar belakang InnoDB, seperti menyiram halaman dari kumpulan buffer dan menggabungkan data dari buffer insert.

SARAN # 2

Agar data dan indeks terpisah dari tablespace sistem (ibdata1), Anda perlu melakukan restrukturisasi lengkap InnoDB. Kedengarannya rumit, tetapi sangat mudah. Saya menulis tentang ini di DBA StackExchange (29 Agustus 2012) dan di StackOverflow (29 Okt 2010) . Langkah dasarnya adalah

  • Lari SET GLOBAL innodb_fast_shutdown = 0;
  • mysqldump semua data ke dump SQL
  • service mysql stop
  • Hapus file-file berikut
    • ibdata1
    • ib_logfile0
    • ib_logfile1
  • service mysql start

Sebelum Anda menjalankan service mysql start, tambahkan baris ini kemy.cnf

innodb_open_files=32768

Dengan begitu, akan ada file menangani yang didedikasikan untuk masing-masing tabel. Standarnya adalah 300. Pegangan file diketahui telah di-cache. Akan ada penurunan jika Anda mengatur ini sangat tinggi dan menekan langit-langit dengan cepat . Ini seharusnya tidak menjadi masalah jika Anda mengerjakan sejumlah kecil tabel.

RolandoMySQLDBA
sumber
Terima kasih atas saran Anda. Saya akan mencoba saran # 2 sekarang, dan aku akan menyesuaikan innodb_read_io_threads, innodb_write_io_threadsdan `innodb_io_capacity'.
inohiro
"Hapus file-file berikut ibdata1" Sheesh, tanpa peringatan.
magallanes
6

Ada seluruh dokumen yang didedikasikan untuk memuat data secara massal ke InnoDB. Poin utama:

  1. nonaktifkan autocommit untuk menghindari flush log tambahan untuk setiap pernyataan penyisipan: SET autocommit=0;...sql import;COMMIT;
  2. nonaktifkan cek asing dan unik (Anda tidak dapat sepenuhnya menonaktifkan semua indeks):

    SET unique_checks=0;
    SET foreign_key_checks=0;
    
  3. Secara potensial mengatur innodb_autoinc_lock_mode menjadi 2, bukan 1 (default). Berikut adalah dokumentasi pada pengaturan ini.

Yang ketiga mungkin atau mungkin tidak membantu Anda, jadi saya sarankan membaca tautan itu untuk melihat bagaimana Anda pertama kali memuat data. Misalnya, jika Anda memecah beban menjadi beberapa sisipan untuk dijalankan secara bersamaan, itu pasti akan membantu Anda mengatur nilainya menjadi 2. Jika Anda melakukan satu penyisipan multi-garis besar, itu tidak akan berbuat banyak (jika ada) untuk Tolong.

Karena Anda memutar log biner untuk penyisipan awal ini, Anda seharusnya tidak peduli dengan kesenjangan dalam angka kenaikan otomatis (jika melakukan penyisipan bersamaan).

Derek Downey
sumber
Terima kasih atas jawaban Anda! Sisipan massal terlihat sangat cepat, dan saya akan mencobanya nanti.
inohiro
Hanya dengan menyetel autocommit = 0, peningkatan yang dilakukan oleh pesanan besar. Terima kasih!
Alex Barker
1

Anda dapat menggunakan metode berikut untuk mempercepat pemasangan:

  • Jika Anda memasukkan banyak baris dari klien yang sama secara bersamaan, gunakan INSERTpernyataan dengan banyak VALUESdaftar untuk memasukkan beberapa baris sekaligus. Ini jauh lebih cepat (beberapa kali lebih cepat dalam beberapa kasus) daripada menggunakan INSERTpernyataan baris tunggal yang terpisah . Jika Anda menambahkan data ke tabel kosong, Anda bisa menyetel variabel bulk_insert_buffer_size untuk membuat penyisipan data lebih cepat.
  • Saat memuat tabel dari file teks, gunakan LOAD DATA INFILE. Ini biasanya 20 kali lebih cepat daripada menggunakan INSERTpernyataan. Lihat
  • Manfaatkan fakta bahwa kolom memiliki nilai default. Masukkan nilai secara eksplisit hanya ketika nilai yang dimasukkan berbeda dari standar. Ini mengurangi penguraian yang harus dilakukan MySQL dan meningkatkan kecepatan memasukkan.
  • Lihat Bagian 9.5.5, “ Memuat Data Massal untuk Tabel InnoDB ” untuk tip khusus untuk tabel InnoDB.
pengguna2432735
sumber
0

Paket A: "Batch" INSERT - beberapa baris per pernyataan INSERT. Sarankan sekitar 1000 baris per pernyataan. autocommit = aktif, tidak ada BEGIN eksplisit ... KOMIT

Paket B: LOAD DATA

Jika Anda memasukkan terlalu banyak baris sekaligus, InnoDB harus melakukan lebih banyak pekerjaan untuk dapat mengembalikan sisipan jika ada kerusakan. Untuk alasan ini, saya tidak setuju dengan autocommit = off, yang akan membuat seluruh set menjadi satu transaksi.

LOAD DATA dari seluruh rangkaian baris mungkin memiliki masalah yang sama, tetapi cukup cepat.

buffer_pool = 5G dari 6G berada di ambang terlalu besar. Jika ada swapping, kinerja akan anjlok.

PARTISIONing mungkin akan membuatnya lebih lambat.

SHOW CREATE TABLE - Kunci sekunder dapat menjadi kendala serius.

Apakah Anda menggunakan InnoDB? atau XtraDB?

Rick James
sumber
Terima kasih atas jawaban Anda. Saya menggunakan InnoDB. Saya lebih suka Plan A daripada Plan B. LOAD DATAterlihat begitu cepat, tetapi kita perlu menulis data ke teks sekaligus sebagai CSV, lalu gunakan LOAD DATAkan? / Saya akan mengatur buffer_pool_sizeke 4GB.
inohiro