Menambahkan indeks ke tabel mysql besar

13

Saya punya meja

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) unsigned NOT NULL AUTO_INCREMENT,
installmentint (10) unsigned NOT NULL,
on_datetanggal NOT NULL,
actual_datetanggal DEFAULT NULL,
payment_typeint (11) NOT NULL,
scheduled_principal_outstandingdesimal (65,0) NOT NULL,
scheduled_principal_duedecimal (65,0) BUKAN NULL,
scheduled_interest_outstandingdesimal (65,0) BUKAN NULL,
scheduled_interest_duedesimal (65,0) BUKAN NULL,
currencyint (11) BUKAN NULL,
updated_atdatetime BUKAN NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime BUKAN NULL DEFAULT ' 2013-01-06 14:29:16 ',
loan_base_schedule_idint (10) unsigned NOT NULL,
lending_idint (10) unsigned NOT NULL,
rescheduletinyint (1) DEFAULT' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due), KEY ( ),
KEY index_bslt_lending(lending_id),
KUNCI index_bslt_actualdate( actual_date),
KEY index_bslt_spsila ( loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
KEY index_bslt_ondate( on_date),
KEY index_bslt_oa( on_date, actual_date),
KEY index_bslt_ol( on_date, loan_base_schedule_id),
KEY index_bslt_oli( on_date, lending_id)
) ENGINE = InnoDB AUTO_INCREMENT = 30.410.126 DEFAULT CHARSET = utf8 |

Sekarang tabel ini memiliki 30 juta catatan di dalamnya, saya perlu menambahkan dua indeks lagi untuk ini dan sepertinya butuh bertahun-tahun untuk menambahkannya.

ubah tabel base_schedule_line_items tambahkan indeks index_bslt_sla (dijadwalkan_principal_due, actual_date, lending_id);
ubah tabel base_schedule_line_items tambahkan indeks index_bslt_ssla (dijadwalkan_principal_due, terjadwal_interest_due, lending_id, actual_date);

Saya menggunakan query yang disebutkan di bawah ini untuk mengetahui ukuran tabel

SELECT table_name AS "Tables", round ((((data_length + index_length) / 1024/1024), 2) "Ukuran dalam MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

Hasilnya keluar sebagai

base_schedule_line_items | 20111.00

Saya menggunakan ini hanya untuk menghitung panjang data dan meninggalkan panjang indeks

SELECT table_name AS "Tables", round ((((data_length) / 1024/1024), 2) "Ukuran dalam MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

dan hasilnya

base_schedule_line_items | 9497.00

Indeks

KEY index_bslt_actualdate (actual_date),
KEY index_bslt_spsila (loan_base_schedule_id, dijadwalkan_principal_due, terjadwal_interest_due, aktual_date),
KEY index_bslt_ondate (on_date),
KEY index_bslt_dapatditangguhkan, dengan _dapatkan_dapatdibandingkan dengan_data_data_Kunci_ditanggal, dengan
KEY index_bslt_document , KEY index_bslt_document , KEY index_bslt_date_date , KEY index_bslt_document, ke_pengaturan_dana_delanjakan_dua hari_dua hari,
KEY index_bslt_do

ditambahkan oleh saya, tetapi saya tidak yakin atau untuk apa indeks lain ditambahkan. Ini aplikasi yang cukup besar. Sekarang saya perlu menambahkan dua indeks yang disebutkan di atas karena mereka membantu saya mengekstraksi laporan menggunakan pernyataan pilih dan saya merasa sangat sulit untuk menambahkannya. Bantuan apa pun akan sangat dihargai

pengguna2294477
sumber

Jawaban:

16

Aktivitas mengubah tabel besar dilakukan secara bertahap:

  1. Buat tabel baru dengan bidang yang diperlukan dan indeks katakan dalam test DB (hanya struktur)
  2. Buang data dari tabel yang ada dan muat yang sama ke tabel yang baru dibuat di test DB
  3. Sekarang umumkan waktu henti Anda :)
  4. Tukar tabel dengan mengganti nama - RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;Ini adalah operasi atom yang mengambil sepersekian detik.
  5. Muat catatan tambahan ke tabel yang baru dibuat (catatan yang datang setelah dumping dan kemudian memuat). Langkah ini dapat dilakukan sebelum Langkah: 3 juga sekali untuk mengurangi waktu henti Anda.
  6. Dan sistem Anda kembali

Beberapa catatan:

  1. Anda tidak perlu menekan skema informasi langsung seperti ini, coba gunakan SHOW TABLE STATUS from db like 'table_name'
  2. Kecepatan tabel alter lebih atau kurang terkait dengan kecepatan I / O. Terakhir kali ketika kami menjalankan tabel alter langsung (tanpa langkah-langkah di atas), kami memiliki ukuran tabel + 40GB yang dibutuhkan sekitar 4 jam. Jika data 20GB Anda memakan waktu bertahun-tahun, Anda sedang mengerjakan beberapa mesin yang sudah ketinggalan zaman.
  3. Juga drop dari indeks yang tidak diinginkan seperti index_bslt_ondate, index_base_schedule_line_items_loan_base_schedulekarena beberapa indeks lainnya memiliki kolom paling kiri sebagai kolom yang diindeks

Harap beri tahu saya jika Anda memerlukan klarifikasi tentang salah satu langkah ini.

Sunting: Skrip python sederhana untuk mengotomatiskan proses https://github.com/georgecj11/hotswap_mysql_table.git

georgecj11
sumber
10

Anda dapat menggunakan alat seperti pt-online-schema-change untuk menambahkan indeks tanpa memblokir aplikasi Anda. Logika dasarnya adalah sebagai berikut:

  • buat salinan tabel kosong dengan indeks baru
  • tambahkan pemicu ke tabel yang ada sehingga setiap perubahan yang mengenai tabel akan diterapkan ke salinan tabel *
  • mulai menyalin baris dari tabel lama ke yang baru
  • setelah penyalinan selesai, tukar tabel keluar
  • jatuhkan meja lama

* Alat tidak berfungsi jika ada pemicu yang ada di atas meja

Perilaku swapping dan dropping dapat disesuaikan berdasarkan opsi yang diteruskan ke alat.

Juga, ada masalah dengan kunci asing, jadi pastikan untuk membaca dokumentasi alat ini untuk memahami sepenuhnya apa yang dilakukannya.

Dan tentu saja, adalah bijaksana untuk memastikan Anda memiliki cadangan tabel untuk dapat mengembalikannya jika diperlukan.

Derek Downey
sumber