@kyanny's blog

創造性は記憶によるところが大きい - 黒澤明

insert into select ... で extended-insert したい

何百万行くらいのテーブルに、カラムを追加しつつインデックスも追加したい。これを一番時間をかけずにやるにはどうしたらいいか試行錯誤。

ふつうに alter table すると一個インデックス貼るだけで夜が明けてしまったので何個もやると人生が終わってしまうおそれがある。ので不採用。

次に mysqldump を使い --no-data でスキーマだけ取り出してテーブル定義を書き換えて・・・と、インデックス貼ってる最中に、カラム追加したら dump した巨大な insert が軒並み使えないじゃん、ということに気づいてがっくり。

煮詰まったので昼飯を食いにいって、しかし頭の中はそれでいっぱいなので食欲もわかずたいして食いたくもない飯を食うための店を探してブツブツ独り言をいいながら夢遊病者のようにウロウロしていたら insert into select ... という手を思いついた。

insert into table2 col1, col2, col3, 'COL4' select table1 from col1, col2, col3 という風にしてやる。新しく追加したカラムは全部同じ値で埋めて構わないのでこれで問題ない。

これはたぶん700万行あったら700万回 insert するので対して早いわけではない(とおもう)。さらに一行入れるごとにインデックスを作られたらたまらないので alter table table2 disable keys しておく。これにさらに extended-insert ができたら相当早くなると思う。けどないので仕方なく終わるのを待つ。 alter table add index ... を何度も走らせるよりはましであってほしい。

カラムが一個足りませんでした!みたいなのはいろいろやってるうちにどうしても起こりうることなので仕方ないとして、インデックス足りませんでした!みたいなのは「雰囲気でインデックスはっといても結局ピントが外れてたりして使えないことが多いので最初は最低限にして開発しつつ貼るべきインデックスを見極めていってまとめて貼ってから仕上げてリリース」というのを考えていたんだけどそれにしても全然貼らないのはやっぱり辛いなと思った。