簡體   English   中英

MySQL的alter table查詢非常慢

[英]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. 在應用索引更改之前,請執行以下兩個語句,並在完成索引更改后將值更改回1。

     SET unique_checks=0; SET foreign_key_checks=0; 
  2. 創建多個二級索引時,請將它們放在一個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

他們基本上:

  1. 創建重復的表
  2. 創建觸發器以同步表
  3. 批量復制數據
  4. 校驗
  5. 交換表

永遠,但誰在乎,因為這意味着您可以在不停機的情況下更改列。

你的表有1500萬行,這是一些東西。 ALTER TABLE涉及復制表中的所有數據並重新創建索引。 作為第一個測量,嘗試在文件系統中復制數據文件(item_catalog_map.MYD,如果它是MyISAM),並查看需要多長時間。 這是ALTER TABLE 至少要采用的時間。

為了最大限度地減少我想要更改的大表的鎖定,我執行以下操作:

  • 根據現有表創建一個新的空表,並更改此新的空表。
  • 執行大表的mysqldump,使其在大表中的每個記錄都有一個完整的insert語句(開關-c和--skip-extended-insert)
  • 使用空重命名的large_table將此mysqldump導入另一個(空)數據庫。
  • 從另一個數據庫中獲取此新重命名表的mysqldump,並將其導入原始數據庫
  • 在原始數據庫中重命名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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM