[英]MySQL very slow for alter table query
為什么簡單地更新此表以添加一列需要一個多小時? 該表有 15M 行。 它有 2 個索引和一個單鍵主鍵。 ALTER TABLE 查詢現在已經處於“復制到 tmp 表”狀態 1 小時 15 分鍾。
ALTER TABLE `frugg`.`item_catalog_map`
ADD COLUMN `conversion_url` TEXT NULL DEFAULT NULL
桌子:
mysql> describe item_catalog_map;
+------------------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+---------------+------+-----+---------+-------+
| catalog_unique_item_id | varchar(255) | NO | PRI | NULL | |
| catalog_id | int(11) | YES | MUL | NULL | |
| item_id | int(11) | YES | MUL | NULL | |
| price | decimal(10,2) | YES | | 0.00 | |
+------------------------+---------------+------+-----+---------+-------+
mysql> show index from item_catalog_map;
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
| item_catalog_map | 0 | PRIMARY | 1 | catalog_unique_item_id | A | 15485115 | NULL | NULL | | BTREE | |
| item_catalog_map | 1 | IDX_ACD6184FCC3C66FC | 1 | catalog_id | A | 18 | NULL | NULL | YES | BTREE | |
| item_catalog_map | 1 | IDX_ACD6184F126F525E | 1 | item_id | A | 15485115 | NULL | NULL | YES | BTREE | |
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
MySQL的ALTER TABLE性能可能會成為非常大的表的問題。 MySQL通過創建具有所需新結構的空表,將舊表中的所有數據插入新表並刪除舊表來執行大多數更改。 這可能需要很長時間,特別是如果您的內存不足並且表很大並且有很多索引。 許多人都有使用ALTER TABLE操作的經驗,這些操作需要數小時或數天才能完成。
無論如何,如果您需要繼續使用alter table,可能以下資源可以幫助您:
如果您不關心停機時間,我的建議是使用三個單獨的ALTER TABLE
語句。 第一個語句刪除所有現有的二級索引。 第二個語句應用所有與列相關的更改。 最后一個語句將刪除的二級索引添加回來並應用其他索引更改。
另外兩個提示:
在應用索引更改之前,請執行以下兩個語句,並在完成索引更改后將值更改回1。
SET unique_checks=0; SET foreign_key_checks=0;
創建多個二級索引時,請將它們放在一個ALTER TABLE
語句中,而不是多個單獨的ALTER TABLE
語句中。
下圖顯示了性能差異。 方法1是你的方法,方法2是我的方式。 方法2與50米工作台的方法1相比花費約3.47%的時間。 該解決方案僅適用於MySQL(> = 5.5)InnoDB引擎。
Percona工具是大桌子的救星。
http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html
他們基本上:
永遠,但誰在乎,因為這意味着您可以在不停機的情況下更改列。
你的表有1500萬行,這是一些東西。 ALTER TABLE涉及復制表中的所有數據並重新創建索引。 作為第一個測量,嘗試在文件系統中復制數據文件(item_catalog_map.MYD,如果它是MyISAM),並查看需要多長時間。 這是ALTER TABLE 至少要采用的時間。
為了最大限度地減少我想要更改的大表的鎖定,我執行以下操作:
在原始數據庫中重命名large_table和large_table_new。
mysql> create table DATABASE_NAME.LARGE_TABLE_NEW like DATABASE_NAME.LARGE_TABLE; mysql> alter table DATABASE_NAME.LARGE_TABLE_NEW add column NEW_COLUMN_NAME COL_DATA_TYPE(SIZE) default null; $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p DATABASE_NAME LARGE_TABLE > LARGE_TABLE.sql mysql> create table test.LARGE_TABLE like DATABASE_NAME.LARGE_TABLE; $ mysql -u root -p -D test < LARGE_TABLE.sql mysql> rename table test.LARGE_TABLE to test.LARGE_TABLE_NEW; $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p test LARGE_TABLE_NEW > LARGE_TABLE_NEW.sql $ mysql -u root -p -D DATABASE_NAME < LARGE_TABLE_NEW.sql mysql> rename table DATABASE_NAME.LARGE_TABLE to DATABASE_NAME.LARGE_TABLE_OLD, DATABASE_NAME.LARGE_TABLE_NEW to DATABASE_NAME.LARGE_TABLE;
我遇到了同樣的問題,我只是使用“sudo service mysql restart”[ubuntu] 重新啟動了 mysql 服務,此后立即執行了更改表命令。
我有一個類似的問題,對於在 MariaDB Docker 容器中運行的具有 1100 萬行的表來說, ALTER TABLE
的速度非常慢。 同樣的ALTER TABLE
在同樣有 1100 萬行的 RDS 實例上運行得非常快。
我正在運行 Mac OS 12.4,Docker 容器的數據位於文件系統卷上。 正如其他答案所指出的那樣,瓶頸是臨時表的創建。
修復是在 Docker 實驗設置中啟用 VirtioFS。 然后, ALTER TABLE
大約需要 10 分鍾,而不是可能需要 8 小時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.