LoginSignup
8
11

More than 5 years have passed since last update.

MySQLのテーブルローテーションなど

Last updated at Posted at 2016-08-30

ここにも書きましたが、近々社内の障害対応訓練があります。
訓練で使う(かもしれない)ネタをあげておかないとブーイングが出そうなので、非常にありがちな内容ですが、ここにあげておきます。

テーブル定義を見る

まずはDESC。使うテーブルは前にあげたネタで使ったやつです。

mysql> USE cardi_test;
Database changed

mysql> DESC test_data;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | bigint(20)  | NO   | PRI | NULL    |       |
| name  | varchar(40) | NO   |     | NULL    |       |
| flag  | int(1)      | NO   | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

とりあえず構造はわかりますが、INDEXがわかりづらいので、CREATE文の内容を見てみます。

mysql> SHOW CREATE TABLE test_data\G
*************************** 1. row ***************************
       Table: test_data
Create Table: CREATE TABLE `test_data` (
  `id` bigint(20) NOT NULL,
  `name` varchar(40) NOT NULL,
  `flag` int(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_flag` (`flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

この例にはありませんが、パーティショニングの定義は、ただのDESCだけではわからないので要注意です。

ちなみに、今まで何気なく使っていたので全然気付いていませんでしたが、DESC(DESCRIBE)文はEXPLAIN文のシノニムだそうです。

mysql> EXPLAIN test_data;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | bigint(20)  | NO   | PRI | NULL    |       |
| name  | varchar(40) | NO   |     | NULL    |       |
| flag  | int(1)      | NO   | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> DESC SELECT * FROM test_data;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | test_data | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql>

テーブルをコピーする

作業ミスに備えて、バックアップのためにテーブルをコピーすることがあると思いますが、うっかりするとINDEXやパーティショニングの定義が抜け落ちてしまいます。

mysql> CREATE TABLE test_data2 AS SELECT * FROM test_data;
Query OK, 10000 rows affected (0.43 sec)
Records: 10000  Duplicates: 0  Warnings: 0

mysql> DESC test_data2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | bigint(20)  | NO   |     | NULL    |       |
| name  | varchar(40) | NO   |     | NULL    |       |
| flag  | int(1)      | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> SHOW CREATE TABLE test_data2\G
*************************** 1. row ***************************
       Table: test_data2
Create Table: CREATE TABLE `test_data2` (
  `id` bigint(20) NOT NULL,
  `name` varchar(40) NOT NULL,
  `flag` int(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

セカンダリINDEXどころか、PRIMARY KEYすらありませんね。
というわけで、こちらを使いましょう。

mysql> CREATE TABLE test_data3 LIKE test_data;
Query OK, 0 rows affected (0.02 sec)

mysql> DESC test_data3;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | bigint(20)  | NO   | PRI | NULL    |       |
| name  | varchar(40) | NO   |     | NULL    |       |
| flag  | int(1)      | NO   | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> SHOW CREATE TABLE test_data3\G
*************************** 1. row ***************************
       Table: test_data3
Create Table: CREATE TABLE `test_data3` (
  `id` bigint(20) NOT NULL,
  `name` varchar(40) NOT NULL,
  `flag` int(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_flag` (`flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

INDEXも正しくコピーされました。

テーブルをローテーションする

先の例の「CREATE TABLE … LIKE」構文は、当然ですが単独でも使えますので、テーブル構造だけコピーして空のテーブルを作り、レコードが入ったテーブルを別名に変更することで、テーブルローテーションをすることもできます。

mysql> CREATE TABLE test_data_new LIKE test_data;
Query OK, 0 rows affected (0.02 sec)

mysql> RENAME TABLE test_data TO test_data_old, test_data_new TO test_data;
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT COUNT(*) FROM test_data;
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(*) FROM test_data_old;
+----------+
| COUNT(*) |
+----------+
|    10000 |
+----------+
1 row in set (0.00 sec)

mysql> DESC test_data;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | bigint(20)  | NO   | PRI | NULL    |       |
| name  | varchar(40) | NO   |     | NULL    |       |
| flag  | int(1)      | NO   | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> SHOW CREATE TABLE test_data\G
*************************** 1. row ***************************
       Table: test_data
Create Table: CREATE TABLE `test_data` (
  `id` bigint(20) NOT NULL,
  `name` varchar(40) NOT NULL,
  `flag` int(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_flag` (`flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>

ローテーションに合わせてテーブル構造を変えたいときなどは、「CREATE TABLE … LIKE」構文を使わずに新しいCREATE文を発行したくなりますが、INDEXやパーティション定義などをうっかり忘れてしまいがちです。
「CREATE TABLE … LIKE」構文に続けてALTER文を発行する方法でミスを防ぐこともできますので(空のTABLEに対してのALTERは瞬時に終わります)、検討してみてください。

8
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
11