为什么只需更新此表以添加列需要一个多小时?该表有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 | |
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+
答案 0 :(得分:55)
MySQL的ALTER TABLE性能可能会成为非常大的表的问题。 MySQL执行 通过创建具有所需新结构的空表,将旧表中的所有数据插入新表并删除旧表来进行大多数更改。这可能需要很长时间,特别是如果您的内存不足并且表很大并且有很多索引。许多人都有使用ALTER TABLE操作的经验,这些操作需要数小时或数天才能完成。
无论如何,如果您需要继续使用alter table,可能以下资源可以帮助您:
答案 1 :(得分:24)
如果您不关心停机时间,我的建议是使用三个单独的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引擎。
答案 2 :(得分:8)
Percona工具是大桌子的救星。
http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html
他们基本上是:永远,但谁在乎,因为这意味着您可以在不停机的情况下更改列。
答案 3 :(得分:7)
你的桌子有1500万行,这是什么。 ALTER TABLE涉及复制表中的所有数据并重新创建索引。作为第一个测量,尝试在文件系统中复制数据文件(item_catalog_map.MYD,如果它是MyISAM),并查看需要多长时间。这是ALTER TABLE 至少的时间。
答案 4 :(得分:6)
为了最大限度地减少我想要更改的大表的锁定,我执行以下操作:
在原始数据库中重命名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;
答案 5 :(得分:-1)
如果您一次更改多个列,可能需要比预期更长的时间。而是尝试一次更改一次列。我没有找到技术方面,但我遇到了问题,并从中得到了解决。