【AWS】RDS for PostgreSQLで文字コード、タイムゾーンを指定してデータインポートしてみた

2014.02.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。昨年のre:InventにてRDSのPostgreSQL対応が発表されました。

最近オンプレミスで稼働しているPostgreSQL DBのデータをインポートする機会がありましたので、本日はその備忘録となります。

環境

エクスポート元のバージョン
7.4.8
インポート先のバージョン
9.3.1
インポート先DBの管理者ユーザー
awsuser
インポート先DBのエンドポイント
postgres.ap-northeast-1.rds.amazonaws.com

インポート前の事前作業

既存のデータをインポートするということで以下のような作業を行いました。

  • タイムゾーンをJST(+0900)に変更
  • 文字コードをEUC-JPに変更

タイムゾーンをJST(+0900)に変更

デフォルトのパラメーターで時刻を取得するとUTCで返ってきます。DBに接続してcurrent_timestampを実行して確認してみましょう。

$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1
template1=> select current_timestamp;
              now
-------------------------------
 2014-01-31 04:26:11.506471+00
(1 行)

+00とUTCで結果が返ってきています。そこでパラメーターグループでタイムゾーンをJST変更します。なおパラメーターグループはdefault.postgres9.3をベースにインスタンス独自のパラメーターグループを作成済みです。

  "timezone"    = "JST-9"

パラメーターグループはリブートなしで反映され"in-sync"になりますが、実際にDBに反映されるためにはリブートが必要になります。リブートしたら再度DBに接続してcurrent_timestampを実行してみます。

$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1
template1=> select current_timestamp;
              now
-------------------------------
 2014-01-31 14:33:18.275635+09
(1 行)

ちゃんとJSTで時刻が返ってきています!

PostgreSQLのタイムゾーン設定についてはPostgreSQL 9.3.2文書の「クライアント接続デフォルト」「日付/時刻データ型」を参考にしました。

文字コードをEUC-JPに変更

パラメーターグループで下記4つのパラメーターを変更します。

  "lc_messages" = "ja_JP.eucJP"
  "lc_monetary" = "ja_JP.eucJP"
  "lc_numeric"  = "ja_JP.eucJP"
  "lc_time"     = "ja_JP.eucJP"

設定によってどのようにPostgreSQLの挙動が変わるのかは「ロケール(国際化と地域化) — Let's Postgres」が詳しいです。

インポート作業

pg_dumpコマンドで取得したダンプファイルをインポートします。インポート前にcreateuserコマンドを使って必要なユーザー(user1)を作っておきましょう。

$ createuser -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -P user1
(user1のパスワードを入力する)
(管理者ユーザー awsuser のパスワードを入力する)

次にインポート先のDB(mydb)を作成します。

2014/02/19 追記
lc_collate や lc_ctype がUTF-8のままだとorder by句lower関数の結果が意図しないものになります。この2つはcreate database時のみ指定可能なため記述を追加しました。

$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d template1
template1=> create database mydb LC_COLLATE 'ja_JP.eucJP' LC_CTYPE 'ja_JP.eucJP' ENCODING 'EUC_JP' TEMPLATE template0;
CREATE DATABASE

template1=> \l
                                         データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) |      アクセス権
-----------+----------+------------------+-------------+-------------------+-----------------------
 postgres  | awsuser  | UTF8             | en_US.UTF-8 | en_US.UTF-8       |
 rdsadmin  | rdsadmin | UTF8             | en_US.UTF-8 | en_US.UTF-8       | rdsadmin=CTc/rdsadmin
 mydb      | awsuser  | EUC_JP           | ja_JP.eucJP | ja_JP.eucJP       |
 template0 | rdsadmin | UTF8             | en_US.UTF-8 | en_US.UTF-8       | =c/rdsadmin          +
           |          |                  |             |                   | rdsadmin=CTc/rdsadmin
 template1 | awsuser  | UTF8             | en_US.UTF-8 | en_US.UTF-8       | =c/awsuser             +
           |          |                  |             |                   | awsuser=CTc/awsuser

psqlコマンドでダンプファイル(pg_dump.sql)をインポートします。インポートログ(pg_import.log)も出力しておきましょう。

$ psql -U awsuser -h postgres.ap-northeast-1.rds.amazonaws.com -d mydb \
  -f pg_dump.sql --log-file pg_import.log

インポートが完了したら\dコマンドでテーブル、ビュー、シーケンスの一覧を表示しオブジェクトが作成されていることを確認しましょう。

$ psql -U user1 -h postgres.ap-northeast-1.rds.amazonaws.com -d mydb
mydb=> \d
                      リレーションの一覧
 スキーマ |            名前             |     型     | 所有者
----------+-----------------------------+------------+--------
 public   | my_tbl                      | テーブル   | user1
 public   | my_seq                      | シーケンス | user1

問題なくインポートできていますね!

まとめ

PostgreSQLにさわるのは15年ぶりくらいなので、久々だと色々忘れていて時間がかかってしまいました。

なおm1.smallだと15MBほどのファイルのインポートに14分ほどかかりました。なんだかinsertのたびにcommitが走っているような気がします。autocommitでも有効になっているのでしょうか?もうちょっとインポートが早くなる方法を引き続き探してみたいと思います。