Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Penyisipan MySql ke dalam kueri pemilihan terlalu lambat untuk menyalin 100 juta baris

INSERT ... SELECT ... kueri memperoleh kunci BERSAMA pada baris yang dibaca dari tabel sumber di SELECT. Tetapi dengan memproses potongan baris yang lebih kecil, kunci tidak bertahan terlalu lama.

Kueri dengan LIMIT ... OFFSET akan menjadi lebih lambat dan lebih lambat saat Anda maju melalui tabel sumber. Pada 10.000 baris per potongan, Anda perlu menjalankan kueri itu 10.000 kali, masing-masing harus memulai dari awal dan memindai tabel untuk mencapai OFFSET baru.

Apa pun yang Anda lakukan, menyalin 100 juta baris akan memakan waktu cukup lama. Ini melakukan banyak pekerjaan.

Saya akan menggunakan pt-archiver , alat gratis yang dirancang untuk tujuan ini. Ini memproses baris dalam "potongan" (atau himpunan bagian). Ini akan menyesuaikan ukuran potongan secara dinamis sehingga setiap potongan membutuhkan waktu 0,5 detik.

Perbedaan terbesar antara metode Anda dan pt-archiver adalah pt-archiver tidak menggunakan LIMIT ... OFFSET , ia berjalan di sepanjang indeks kunci utama, memilih potongan baris berdasarkan nilai, bukan berdasarkan posisi. Jadi setiap potongan dibaca lebih efisien.

Kembali komentar Anda:

Saya berharap membuat ukuran batch lebih kecil — dan meningkatkan jumlah iterasi — akan membuat masalah kinerja lebih buruk , tidak lebih baik.

Alasannya adalah ketika Anda menggunakan LIMIT dengan OFFSET , setiap kueri harus memulai kembali dari awal tabel, dan menghitung baris hingga OFFSET nilai. Ini menjadi lebih lama dan lebih lama saat Anda mengulangi tabel.

Menjalankan 20.000 kueri mahal menggunakan OFFSET akan memakan waktu lebih lama daripada menjalankan 10.000 kueri serupa. Bagian yang paling mahal tidak akan membaca 5.000 atau 10.000 baris, atau memasukkannya ke tabel tujuan. Bagian yang mahal akan melewati ~50.000.000 baris, berulang-ulang.

Sebagai gantinya, Anda harus mengulangi tabel dengan nilai bukan dengan offset.

INSERT IGNORE INTO Table2(id, field2, field3)
        SELECT f1, f2, f3
        FROM Table1
        WHERE id BETWEEN rowOffset AND rowOffset+limitSize;

Sebelum loop, kueri MIN(id) dan MAX(id), dan mulai rowOffset pada nilai minimum, dan ulangi hingga nilai maksimum.

Ini adalah cara kerja pt-archiver.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menginstal Sonar di Ubuntu dengan mysql

  2. Masalah saat mencoba menggunakan MySQL bersama dengan Emacs

  3. PDO::__construct():Server mengirim charset (255) yang tidak diketahui klien. Tolong, laporkan ke pengembang

  4. Tipe data desimal adalah pembulatan nilai

  5. MySQL bersyarat ORDER BY ASC/DESC untuk kolom tanggal