Một cách chắc chắn để tăng tốc ALTER TABLE là xóa các chỉ mục không cần thiết
Dưới đây là các bước ban đầu để tải phiên bản mới của bảng
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
;
Xin lưu ý những điều sau:
Tôi đã bỏ source_persona_index vì đây là cột đầu tiên trong 4 chỉ mục khác
- unique_target_persona
- unique_target_object
- nguồn_and_target_object_index
- nguồn_target_persona_index
Tôi đã bỏ target_persona_index vì đây là cột đầu tiên trong 2 chỉ mục khác
- đích_persona_relation_type_index
- đích_persona_relation_type_message_id_index
Tôi đã bỏ đích_persona_relation_type_index vì 2 cột đầu tiên cũng nằm trong target_persona_relation_type_message_id_index
OK Điều đó quan tâm đến các chỉ số không cần thiết. Có chỉ số nào có cardinality thấp? Đây là cách để xác định rằng:
Chạy các truy vấn sau:
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;
Theo câu hỏi của bạn, có khoảng 80.000.000 hàng. Theo nguyên tắc thông thường, Trình tối ưu hóa truy vấn MySQL sẽ không sử dụng một chỉ mục nếu tính chính xác của các cột được chọn lớn hơn 5% tổng số hàng của bảng. Trong trường hợp này, đó sẽ là 4.000.000.
- Nếu
COUNT(DISTINCT sent_at)
> 4.000.000
- sau đó
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Nếu
COUNT(DISTINCT message_id)
> 4.000.000
- sau đó
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Nếu
COUNT(DISTINCT target_object_id)
> 4.000.000
- sau đó
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
Khi tính hữu dụng hoặc vô dụng của các chỉ mục đó đã được xác định, bạn có thể tải lại dữ liệu
#
# 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;
Đó là nó, phải không? ĐẠO !!!
Nếu trang web của bạn đã hoạt động suốt thời gian này, có thể có INSERT chạy chống lại s_relations trong quá trình tải s_relations_new. Làm thế nào bạn có thể lấy lại những hàng còn thiếu?
Đi tìm id tối đa trong s_relations_new và nối thêm mọi thứ sau ID đó từ s_relations. Để đảm bảo rằng bảng được đóng băng và chỉ được sử dụng cho bản cập nhật này, bạn phải có một chút thời gian chết vì mục đích nhận các hàng cuối cùng được chèn vào s_relation_new. Dưới đây là những gì bạn làm:
Trong HĐH, khởi động lại mysql để không ai khác có thể đăng nhập nhưng root @ localhost (vô hiệu hóa TCP / IP):
$ service mysql restart --skip-networking
Tiếp theo, đăng nhập vào mysql và tải các hàng cuối cùng:
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;
Sau đó, khởi động lại mysql bình thường
$ service mysql restart
Bây giờ, nếu bạn không thể gỡ bỏ mysql, bạn sẽ phải thực hiện chuyển đổi mồi trên s_relations. Chỉ cần đăng nhập vào mysql và làm như sau:
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;
Hãy thử một lần !!!
CAVEAT: Một khi bạn hài lòng với thao tác này, bạn có thể bỏ bảng cũ một cách thuận tiện sớm nhất:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
, hiển thị cột cần thay đổi, kiểu dữ liệu của cột và tên mới cho cột.