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
CREATE TABLE s_relations_new LIKE s_relations;
#
# Drop Duplicate Indexes
#
ALTER TABLE s_relations_new
DROP INDEX source_persona_index,
DROP INDEX target_persona_index,
DROP INDEX target_persona_relation_type_index
;
Harap perhatikan hal berikut:
Saya menjatuhkan source_persona_index karena itu adalah kolom pertama dalam 4 indeks lainnya
- unique_target_persona
- unique_target_object
- source_and_target_object_index
- source_target_persona_index
Saya menjatuhkan target_persona_index karena ini adalah kolom pertama dalam 2 indeks lainnya
- target_persona_relation_type_index
- target_persona_relation_type_message_id_index
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:
SELECT COUNT(DISTINCT sent_at) FROM s_relations;
SELECT COUNT(DISTINCT message_id) FROM s_relations;
SELECT COUNT(DISTINCT target_object_id) FROM s_relations;
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.
- Jika
COUNT(DISTINCT sent_at)
> 4.000.000
- kemudian
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Jika
COUNT(DISTINCT message_id)
> 4.000.000
- kemudian
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Jika
COUNT(DISTINCT target_object_id)
> 4.000.000
- kemudian
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
Setelah kegunaan atau kegunaan dari indeks tersebut telah ditentukan, Anda dapat memuat ulang data
#
# Change the Column Name
# Load the Table
#
ALTER TABLE s_relations_new CHANGE sent_at sent_at_new int(11) DEFAULT NULL;
INSERT INTO s_relations_new SELECT * FROM s_relations;
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):
$ service mysql restart --skip-networking
Selanjutnya, masuk ke mysql dan muat baris terakhir itu:
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Kemudian, restart mysql secara normal
$ service mysql restart
Sekarang, jika Anda tidak dapat menghapus mysql, Anda harus melakukan umpan-dan-aktifkan pada s_relations. Cukup login ke mysql dan lakukan hal berikut:
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations_old WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Cobalah !!!
CAVEAT: Setelah Anda puas dengan operasi ini, Anda dapat menjatuhkan meja lama sesegera mungkin:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
, perlihatkan kolom yang perlu diubah, tipe data dari kolom, dan nama baru untuk kolom.