Saya memiliki tabel InnoDB yang ingin saya ubah. Tabel ini memiliki ~ 80 juta baris, dan keluar dari beberapa indeks.
Saya ingin mengubah nama salah satu kolom dan menambahkan beberapa indeks lagi.
- Apa cara tercepat untuk melakukannya (dengan asumsi saya bisa menderita downtime bahkan - server adalah budak yang tidak digunakan)?
- Apakah "polos"
alter table
, solusi tercepat?
Saat ini, yang saya pedulikan hanyalah kecepatan :)
mysql
innodb
alter-table
ddl
Ran
sumber
sumber
SHOW CREATE TABLE tblname\G
, perlihatkan kolom yang perlu diubah, tipe data dari kolom, dan nama baru untuk kolom.sent_at
dan menambahkannya beberapa indeks lagiJawaban:
Salah satu cara pasti untuk mempercepat ALTER TABLE adalah dengan menghapus indeks yang tidak perlu
Berikut adalah langkah-langkah awal untuk memuat versi baru tabel
Harap perhatikan hal berikut:
Saya menjatuhkan source_persona_index karena itu adalah kolom pertama dalam 4 indeks lainnya
Saya menjatuhkan target_persona_index karena ini adalah kolom pertama dalam 2 indeks lainnya
Saya menjatuhkan target_persona_relation_type_index karena 2 kolom pertama juga di target_persona_relation_type_message_id_index
OK Itu menangani indeks yang tidak perlu. Apakah ada indeks yang memiliki kardinalitas rendah? Inilah cara untuk menentukan itu:
Jalankan pertanyaan berikut:
Menurut pertanyaan Anda, ada sekitar 80.000.000 baris. Sebagai aturan praktis, Pengoptimal Permintaan MySQL tidak akan menggunakan indeks jika kardinalitas kolom yang dipilih lebih besar dari 5% dari jumlah baris tabel. Dalam hal ini, itu akan menjadi 4.000.000.
COUNT(DISTINCT sent_at)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX sent_at_index;
COUNT(DISTINCT message_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX message_id_index;
COUNT(DISTINCT target_object_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX target_object_index;
Setelah kegunaan atau kegunaan dari indeks tersebut telah ditentukan, Anda dapat memuat ulang data
Itu dia kan? TIDAK !!!
Jika situs web Anda telah menyala sepanjang waktu ini, mungkin ada INSERT yang berjalan terhadap s_relations selama pemuatan s_relations_new. Bagaimana Anda bisa mendapatkan kembali baris yang hilang itu?
Pergi temukan id maksimum di s_relations_new dan tambahkan semuanya setelah ID itu dari s_relations. Untuk memastikan bahwa tabel dibekukan dan hanya digunakan untuk pembaruan ini, Anda harus memiliki sedikit downtime demi mendapatkan baris terakhir yang dimasukkan ke s_relation_new. Inilah yang Anda lakukan:
Di OS, mulai ulang mysql sehingga tidak ada orang lain yang bisa masuk tetapi root @ localhost (menonaktifkan TCP / IP):
Selanjutnya, masuk ke mysql dan muat baris terakhir itu:
Kemudian, restart mysql secara normal
Sekarang, jika Anda tidak dapat menghapus mysql, Anda harus melakukan umpan-dan-aktifkan pada s_relations. Cukup login ke mysql dan lakukan hal berikut:
Cobalah !!!
CAVEAT: Setelah Anda puas dengan operasi ini, Anda dapat menjatuhkan meja lama sesegera mungkin:
sumber
Jawaban yang benar tergantung pada versi mesin MySQL yang Anda gunakan.
Jika menggunakan 5.6+, penggantian nama dan penambahan / penghapusan indeks dilakukan secara online , yaitu tanpa menyalin semua data tabel.
Cukup gunakan
ALTER TABLE
seperti biasa, sebagian besar instan untuk penggantian nama dan penurunan indeks, dan cukup cepat untuk penambahan indeks (secepat membaca semua tabel sekali).Jika menggunakan 5.1+, dan plugin InnoDB diaktifkan, menambahkan / menghapus indeks akan online juga. Tidak yakin tentang penggantian nama.
Jika menggunakan versi yang lebih lama,
ALTER TABLE
masih yang tercepat — tetapi mungkin akan sangat lambat karena semua data Anda akan dimasukkan kembali ke tabel sementara di bawah tenda.Akhirnya, waktu untuk menghilangkan prasangka mitos. Sayangnya saya tidak memiliki cukup karma di sini untuk mengomentari jawaban, tetapi saya merasa penting untuk memperbaiki jawaban yang paling banyak dipilih. Ini salah :
Sebenarnya sebaliknya .
Indeks berguna untuk memilih beberapa baris, jadi penting mereka memiliki kardinalitas tinggi , yang berarti banyak nilai berbeda dan secara statistik sedikit baris dengan nilai yang sama.
sumber
RENAME TABLE
instan (seperti yang diharapkan) tetapiCHANGE COLUMN
untuk mengganti nama kunci utama melakukan salinan lengkap ... 7 jam! Mungkin hanya karena itu adalah kunci utama? Tidak baik.Saya memiliki masalah yang sama dengan Maria DB 10.1.12, kemudian setelah membaca dokumentasi saya menemukan bahwa ada opsi untuk melakukan operasi "di tempat" yang menghilangkan salinan tabel. Dengan opsi ini, tabel alter sangat cepat. Dalam kasus saya itu adalah:
ini sangat cepat. Tanpa opsi algoritma itu tidak akan pernah berakhir.
https://mariadb.com/kb/en/mariadb/alter-table/
sumber
Untuk mengganti nama kolom,
harus baik dan tidak membawa downtime.
Untuk indeks, pernyataan CREATE INDEX akan mengunci tabel. Jika itu adalah budak yang tidak digunakan seperti yang Anda sebutkan, itu bukan masalah.
Satu opsi lainnya adalah membuat tabel baru yang memiliki nama dan indeks kolom yang tepat. Kemudian Anda bisa menyalin semua data ke dalamnya, lalu jalankan serangkaian
Ini akan meminimalkan waktu henti dengan biaya sementara menggunakan ruang dua kali lipat.
sumber
Saya punya masalah ini juga dan saya menggunakan SQL ini:
Saya harap ini bisa membantu seseorang
Salam,
Akan
sumber