MySQL LOAD DATA INFILE melambat 80% setelah beberapa gigs input dengan mesin InnoDB

14

Saya memuat file 100GB melalui LOAD DATA INFILE. Saya sudah sukses dengan MyISAM, beberapa jam dan selesai.

Saya coba sekarang menggunakan InnoDB. Muatan mulai cepat di lebih dari 10MB / detik (menonton pertumbuhan file tabel, file_per_tabledihidupkan).

Tetapi setelah sekitar 5GB data melambat ke kisaran 2-4MB / detik, karena saya mendapatkan lebih dari 20GB itu turun sekitar 2MB / detik.

Ukuran buffer pool InnoDB adalah 8G. Dan saya telah melakukan hal berikut sebelum menjalankan perintah LOAD DATA INFILE:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

Saya tidak bisa melihat alasan mengapa ia memulai dengan baik dan melambat seiring berjalannya waktu.

Selain itu, dengan menggunakan pengaturan yang sama, saya menjalankan perintah LOAD DATA INFILE yang sama dengan tabel menggunakan InnoDB dan MyISAM dan dataset uji 5GB, MyISAM 20x lebih cepat:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

Ada lagi yang harus saya pertimbangkan untuk mencoba? Mesin MyISAM mampu menjaga laju muat jauh lebih baik.


Detil tambahan:

  • Saya sudah mencoba memuat file secara individual, tidak ada perbedaan.

  • Kebetulan, saya punya 150 file masing-masing 500MB, dalam setiap file kunci diurutkan.

  • Setelah mendapatkan 40GB dalam semalam, 12 jam kemudian, laju muat turun menjadi 0,5MB / detik, yang berarti operasi itu, secara praktis, tidak mungkin.

  • Saya belum menemukan jawaban lain untuk pertanyaan serupa di forum lain, sepertinya bagi saya InnoDB tidak mendukung memuat data dalam jumlah besar ke dalam tabel dengan ukuran lebih dari beberapa GB.

David Parks
sumber

Jawaban:

7

PENGAMATAN # 1

Saya perhatikan Anda dimatikan autocommit. Itu akan menumpuk begitu banyak data di ibdata1. Mengapa?

Ada tujuh (7) kelas informasi yang disimpan di ibdata1:

  • Halaman Data untuk Tabel InnoDB
  • Halaman Indeks untuk Tabel InnoDB
  • Kamus data
  • Buffer Tulis Ganda
    • Jaring Pengaman untuk Mencegah Korupsi Data
    • Membantu Bypass OS untuk Caching
  • Masukkan Buffer (Streamlines Perubahan ke Indeks Sekunder)
  • Segmen kembalikan
  • Batalkan Log
  • Klik Di Sini untuk melihat Representasi Pictorial dari ibdata1

Beberapa info ini dibuat terlihat oleh transaksi tertentu tergantung pada tingkat isolasi. Tindakan seperti itu dapat menghasilkan kunci kunci primer yang tidak diinginkan dan banyak data hantu . Ketika dua hal ini meningkat, Anda seharusnya mengharapkan perlambatan yang wajar.

Rekomendasi: Biarkan autocommit aktif

PENGAMATAN # 2

Saya melihat Anda memiliki ini:

alter table item_load disable keys;

KUNCI DISABLE tidak bekerja dengan InnoDB . Inilah alasannya:

  • MyISAM: DISABLE KEYScukup matikan pembaruan Indeks Sekunder untuk tabel MyISAM. Saat Anda menyisipkan MASUK ke dalam tabel MyISAM dengan kunci yang dinonaktifkan menghasilkan beban tabel cepat bersama dengan bangunan KUNCI UTAMA dan semua indeks unik. Ketika Anda menjalankan ENABLE KEYS, semua Indeks Sekunder dibangun secara linear di atas meja dan ditambahkan ke .MYD.
  • InnoDB: Seperti yang ditunjukkan pada gambar internal InnoDB, tablespave sistem ibdata1memiliki struktur yang didedikasikan untuk Penyisipan Indeks Sekunder. Saat ini, tidak ada ketentuan untuk menangani indeks yang sama dengan MyISAM.

Untuk menggambarkan hal ini, catat upaya saya untuk menjalankan DISABLE KEYS pada tabel InnoDB di MySQL

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

PENGAMATAN # 3

Anda perhatikan bahwa MyISAM memuat 20x lebih cepat dari InnoDB. Apakah Anda ingin menjadi lebih seperti 24-25 kali lebih cepat? Kemudian jalankan yang berikut ini:

ALTER TABLE item_load ROW_FORMAT=Fixed;

Ini akan mempercepat kali INSERT 20-25% tanpa Perubahan DDL lainnya . Efek samping: Tabel MyISAM dapat tumbuh 80% -100%, mungkin lebih besar.

Anda bisa menjalankan ini pada tabel InnoDB juga, tetapi perilaku ACID-compliant dan MVCC dari InnoDB masih akan menjadi hambatan kinerjanya, terutama jika bidang VARCHAR meningkat secara signifikan ibdata1.

RolandoMySQLDBA
sumber
2 pengamatan pertama adalah hal-hal yang saya coba tambahkan untuk memperbaiki masalah setelah saya pertama kali menyadarinya, upaya pertama saya adalah meninggalkan innodb sendirian (matikan saja logging bin). Pada pengamatan ke-3, ukuran data saya sangat bervariasi panjangnya, saya anggap ini akan menjadi masalah? Saya merasa seperti saya hanya perlu menyimpan myisam tabel ini.
David Parks
6

Jawaban akhir untuk pertanyaan ini adalah tidak menggunakan InnoDB untuk tabel referensi besar. MyISAM berteriak dengan cepat, mendekati kecepatan penuh dari kecepatan disk untuk seluruh beban, InnoDB turun. MyISAM sederhana, tetapi dalam hal ini adalah persyaratan dari tabel ini. Untuk tabel referensi sederhana dengan banyak muatan lebih dari LOAD DATA INFILE, MyISAM adalah cara yang harus ditempuh, sejauh ini bagus.

Tetapi perhatikan bahwa jika Anda menjalankan tabel MyISAM dan InnoDB, Anda perlu mempertimbangkan alokasi memori untuk 2 mekanisme caching, setiap mesin memiliki caching uniknya sendiri yang membutuhkan alokasi memori terpisah.

David Parks
sumber
5

Anda dapat mencoba membagi file input Anda menjadi potongan yang lebih kecil.

Saya pribadi menggunakan http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html untuk ini.

Apa yang terjadi jika Anda mendapatkan kunci meja untuk tabel selama impor? Mungkin penguncian baris baris dari InnoDB memperlambatnya (MyISAM menggunakan kunci tabel).

Anda juga dapat membaca di sini untuk ide lebih lanjut: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql

bnadland
sumber
File saya sudah dalam potongan 500MB, saya mem-pip semuanya melalui satu pipa bernama untuk membuat beban lebih mudah, tapi saya akan mencoba pendekatan ini sekarang.
David Parks
Tidak melihat perbedaan di sini, cukup cepat saya melihat penurunan kecepatan dari 11MB / detik ekspansi file DB ke 6MB (setelah sekitar 2GB) data dan terus menurun. Saya memuat semua file dalam for loop, memisahkan panggilan mysql.
David Parks
File pertama dimuat dalam 54s, 2 dalam 3m39s, 3 dalam 3m9s, 4m7s, 5m21s, dan sebagainya. semua file aprox dengan ukuran yang sama.
David Parks
2

Jika PK Anda bukan AUTO_INCREMENT atau data dalam file csv tidak diurutkan pada PK daripada itu mungkin mempengaruhi kinerja dataload. Karena tabel dalam MySQL adalah indeks maka semua data disimpan dalam urutan, jika nilai PK tidak pada AUTO_INCREMENT daripada MySQL harus melakukan banyak pergeseran data untuk mendapatkan data disimpan dalam urutan diurutkan. Ini adalah alasan untuk memuat data yang lebih lambat ketika ukuran tabel mulai tumbuh.

Saya memuat file csv 91GB dengan PK di AUTO_INCREMENT menggunakan LOAD DATA INFILE dan saya tidak melihat penurunan dalam throughput saya. Saya mendapatkan insert 140K hingga 145K per detik. Menggunakan Percona MySQL 5.6.38

KKYadav
sumber