ソフトウェア開発者の日常

こだわりなく書きたいことを書いていきます。

大量データの一括での入れ替え方法

データベースのテーブルに、12万レコードくらいのデータが保存されているテーブルがあります。
このテーブルのデータの更新が必要になりました。

どのレコードが更新対象なのか、あるいは追加、削除の対象なのか、情報がありません。
更新後の元データだけあります。

幸いなことに、12万レコードくらいのデータが保存されているテーブルは、参照して利用をしているだけで、主キーに対してのデータが変わってしまっても、問題は発生しません。
更新の履歴も不要です。

一括で全レコードを削除して、更新後となる新しいデータを入れてしまっても、問題は発生しません。

12万レコードくらいを、一括でテーブルに登録するのは、時間がかかる。

まずは、元データをテスト用のテーブルに登録しました。
Accessのリンクテーブルを使っても、登録自体はできるのでしょうが、非常に時間がかかると、経験上予想しました。

更新後の元データは、CSV形式のファイルのため、CSV形式のファイルを読み込んで、データベースのテーブルに登録するプログラムを作成しました。

テスト用のテーブルを用意して、作成したプログラムでデータを登録すると、20分くらいかかりました。
データを更新するために20分もかかるのは、許容できません。

大量のデータ
Photo by Viktor Talashuk on Unsplash

テーブルの名前を変更すれば、即時完了する

データを登録するために20分かかるのは仕方ないにしても、更新自体は、なるべく短時間で終わらせたいです。

なるべく短時間で、更新したという結果になる方法を考えていたら、12万レコードくらいのデータが保存されているテーブルは、作り直しても問題ないことに気がつきました。

作り直していいのであれば、

  • 12万レコードくらいのデータが保存されているテーブルを削除する。
  • テスト用のテーブルのテーブル名を変更して、12万レコードくらいのデータが保存されているテーブルと同じにする。

の手順で対処ができます。

実際、以下のような手順で試してみました。
データベースは、PostgreSQLです。

-- 既存のテーブル削除
DROP TABLE original_table;

-- 名前を変更するテーブルの主キー制約を削除
ALTER TABLE new_table DROP CONSTRAINT new_table_pkey;

-- テーブル名を変更
ALTER TABLE new_table RENAME TO original_table;

-- 主キー制約を追加
ALTER TABLE original_table ADD CONSTRAINT original_table_pkey PRIMARY KEY(column1);

-- インデックス作成
CREATE INDEX original_table_column1_idx ON original_table USING btree(column1);

この手順で試した結果、1秒かからないで処理は終わっていました。
1秒かからないのであれば許容できるので、この手順で、12万レコードくらいのデータを入れ替えたという結果にしました。


本来なら、このような方法ではなく、更新プログラムを作成して、必要な都度、更新を行っていくべきだと考えています。