このテーブルを更新して列を追加するだけで1時間以上かかるのはなぜですか?このテーブルには15M行があります。 2つのインデックスと1つのキー主キーがあります。 ALTER TABLEクエリは、1時間15分間「tmpテーブルにコピー」状態になっています。
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を続行する必要がある場合、次のリソースが役立つ可能性があります。
ダウンタイムを気にしない場合は、3つのALTER TABLE
ステートメントを使用することをお勧めします。最初のステートメントは、既存のすべてのセカンダリインデックスを削除します。 2番目のステートメントは、すべての列関連の変更を適用します。最後のステートメントは、ドロップされたセカンダリインデックスを追加して戻し、他のインデックスの変更を適用します。
別の2つのヒント:
インデックスの変更を適用する前に、次の2つのステートメントを実行し、インデックスの変更が完了したら値を1に戻します。
SET unique_checks=0;
SET foreign_key_checks=0;
複数のセカンダリインデックスを作成するときは、複数のALTER TABLE
ステートメントではなく、1つのALTER TABLE
ステートメントに入れます。
次の図は、パフォーマンスの違いを示しています。アプローチ1はあなたのアプローチであり、アプローチ2は私の方法です。 50mテーブルのアプローチ1と比較して、アプローチ2は約3.47%時間かかります。このソリューションは、MySQL(> = 5.5)InnoDBエンジンでのみ機能します。
Perconaツールは、大きなテーブルを備えたこのようなものの命の恩人です。
http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html
彼らは基本的に:
永遠にかかりますが、ダウンタイムなしで列を変更できることを意味するため、誰も気にしません。
あなたのテーブルには1500万行があります。 ALTER TABLEでは、テーブルからすべてのデータをコピーして、インデックスを再作成します。最初の測定として、ファイルシステムにデータファイル(MyISAMの場合はitem_catalog_map.MYD)をコピーして、どれくらい時間がかかるかを確認します。これは、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;