Mengapa 'LOAD DATA INFILE' lebih cepat daripada pernyataan INSERT normal?

22

Saya telah membaca sebuah artikel yang menyebutkan bahwa kita dapat mencapai 60.000 sisipan per detik dengan menggunakan LOAD DATA IN FILEpernyataan, yang membaca dari file csv dan memasukkan data ke dalam basis data.

Mengapa harus berbeda dari sisipan normal?

EDIT:
Saya mengurangi perjalanan pulang-pergi dengan menelepon satu INSERTpernyataan:

INSERT INTO tblname
VALUES (NULL,2,'some text here0'),(NULL,2,'some text here1')
    ,(NULL,2,'some text here2'),(NULL,2,'some text here3')
    .....,(NULL,2,'some text here3000');

Bagaimana dengan ini?

ALH
sumber
Saya menulis sebuah artikel di Medium, membandingkan benchmark dengan insert yang diperluas vs LOAD DATA INFILE: insert berkecepatan tinggi dengan MySQL . Intinya: Anda dapat mencapai 65% dari kinerja LOAD DATA INFILEmenggunakan sisipan yang diperluas. Saya mendapat 240.000 sisipan / detik pada perangkat keras modern.
Benjamin

Jawaban:

26

LOAD DATA INFILE dan INSERT yang diperluas masing-masing memiliki keunggulan berbeda.

LOAD DATA INFILE dirancang untuk memuat data tabel secara massal dalam satu operasi bersama dengan lonceng dan peluit untuk melakukan hal-hal seperti:

  • Melewati Garis Awal
  • Melewati Kolom Khusus
  • Mengubah Kolom Tertentu
  • Memuat Kolom Tertentu
  • Menangani Masalah Kunci Duplikat

Lebih sedikit overhead yang diperlukan untuk penguraian

Di sisi lain, jika Anda hanya mengimpor 100 baris, bukan 1.000.000 baris, INSERT yang diperluas masuk akal.

Perhatikan bahwa mysqldump dirancang di sekitar INSERT yang diperluas demi membawa desain tabel bersama dengan data saat ia melakukan injeksi ratusan atau ribuan baris per INSERT. LOAD DATA INFILE selalu menciptakan dichomoty fisik antara skema dan data.

Dari sudut pandang aplikasi, LOAD DATA INFILE juga lebih tidak sensitif terhadap perubahan skema daripada INSERT yang diperluas.

Seseorang dapat bolak-balik pada yang baik, yang buruk, dan buruk menggunakan LOAD DATA INFILE. Apa pun teknik yang Anda gunakan, Anda harus selalu mengatur bulk_insert_buffer_size . Mengapa?

Menurut Dokumentasi MySQL di 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.

Selama bertahun-tahun, saya telah melihat klien setelah klien tidak mengatur ini dan membiarkannya pada 8MB. Kemudian, ketika mereka memutuskan untuk menggunakan LOAD DATA INFILE atau mengimpor mysqldumps, mereka dapat merasakan sesuatu yang salah. Saya biasanya merekomendasikan pengaturan ini ke 256M moderat. Dalam beberapa kasus, 512M.

Setelah Anda memiliki buffer INSERT massal yang cukup besar, menggunakan teknik mana pun diberikan secara akademis dan bermuara pada pilihan pribadi. Untuk aplikasi tempat Anda memasukkan INSERT massal hanya 100 baris sesuai permintaan, tetap menggunakan INSERT yang diperluas.

Dalam semua kewajaran, mengatakan LOAD DATA INFILE lebih cepat daripada pernyataan INSERT normal adalah jenis pernyataan yang dimuat terutama karena konfigurasi tidak diperhitungkan. Bahkan jika Anda menyiapkan patokan antara LOAD DATA INFILE dan INSERT yang diperluas dengan bulk_insert_buffer_size yang tepat, nanosecond yang disimpan pada penguraian setiap baris hanya dapat menghasilkan hasil nominal yang paling baik dalam mendukung LOAD DATA INFILE.

Silakan dan tambahkan ini ke my.cnf

[mysqld]
bulk_inset_buffer_size=256M

Anda juga dapat mengaturnya hanya untuk sesi Anda sebelum meluncurkan INSERT yang diperluas

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

UPDATE 2012-07-19 14:58 EDT

Untuk menjaga hal-hal dalam perspektif, buffer penyisipan massal hanya berguna untuk memuat tabel MyISAM, bukan InnoDB. Saya menulis posting yang lebih baru tentang pemuatan massal InnoDB: Beban Mysql dari infile macet menunggu di hard drive

RolandoMySQLDBA
sumber
4

Sebagian besar sistem manajemen basis data memiliki fasilitas pemuatan massal untuk memuat data dalam volume besar dengan cepat. Sebuah INSERTpernyataan memiliki jumlah signifikan per bagasi pernyataan - penguncian, demarkasi transaksi, pemeriksaan integritas referensial, alokasi sumber daya, I / O yang harus dilakukan berdasarkan per pernyataan.

Operasi penyisipan massal merampingkan proses sehingga barang ini memiliki overhead yang jauh lebih sedikit per baris. DBMS dapat memuat data pesanan dalam jumlah besar secara lebih cepat daripada melalui pernyataan penyisipan.

ConcernedOfTunbridgeWells
sumber
3

Parsing dan mengeksekusi INSERTpernyataan individual membawa overhead yang jauh lebih besar daripada membelah file CSV menjadi kolom dan langsung memuatnya.

Setiap INSERTpernyataan harus diuraikan secara terpisah oleh mesin MySQL & diperiksa validitasnya - ini menghabiskan sumber daya CPU tambahan & juga membutuhkan lebih banyak perjalanan pulang-pergi server <> klien. Ini tidak perlu terjadi ketika memuat massal melalui LOAD DATA INFILE. Ada juga optimisasi yang dapat terjadi saat menggunakan LOAD DATA INFILEmemuat ke tabel kosong. Lihat tautan ini untuk informasi lebih lanjut.

Philᵀᴹ
sumber
lihat bagian EDIT dari pertanyaan saya.
ALH
Perhatikan bahwa tidak ada penguraian overhead saat menggunakan pernyataan yang disiapkan.
Benjamin