pg_bulkloadを使いたくなるケース

  • 大量のデータをインポートしたい
  • 中にはエラーがあるデータがちょこちょこある

に当てはまったので、インストールからやってみた。 やったこと順に列記するので最低限の手順ではないと思う。

rpmからインストールする方法でなく、ソースからやってみることにした。 Ubuntu12.04でインストールしたけど、他のバージョンでもほぼ同じだと思う。

ソースの取得

まずは最新のstableをgithubから取ってくる。ブログ執筆時はこんな感じ。

$ git clone -b VERSION3_1_STABLE https://github.com/ossc-db/pg_bulkload.git

make(失敗)

おもむろにmakeしてみると

$ cd pg_bulkload
$ make

するとpgxs.xmlが無い!というエラーが出て来た

Makefile:17: /usr/lib/postgresql/9.4/lib/pgxs/src/makefiles/pgxs.mk: そのようなファイルやディレクトリはありません

postgresqlは9.2しか入れてないはずなのに何故か9.4のファイルが無いとか言われた。

試行錯誤(失敗)

どうもMakefileを調べてみると、ここで出てくるバージョンはpg_configコマンドで取得するバージョンらしい。面倒なので、手動で9.2のファイルを設定するように変更して、さらにpgxs.mkを入れるためにpostgresql-server-dev-9.2をaptitudeでインストールした。

で、おもむろにmakeすると・・・

$ sudo make
....
/usr/include/postgresql/libpq-fe.h:547:1: エラー: 不明な型名 ‘pg_int64’ です
/usr/include/postgresql/libpq-fe.h:547:50: エラー: 不明な型名 ‘pg_int64’ です
/usr/include/postgresql/libpq-fe.h:551:1: エラー: 不明な型名 ‘pg_int64’ です
/usr/include/postgresql/libpq-fe.h:553:48: エラー: 不明な型名 ‘pg_int64’ です
make[1]: *** [pg_bulkload.o] エラー 1
make[1]: ディレクトリ `/****/pg_bulkload/bin' から出ます
make: *** [all] エラー 2

と結局エラーが出てしまった。ググって調べるとどうもlibpqのバージョンが関連するらしい。調べてみると

$ aptitude show libpq-dev
パッケージ: libpq-dev                    
状態: インストール済み
自動的にインストールされた: いいえ
バージョン: 9.4.0-1.pgdg12.4+1
....

バージョンが9.4になっていたorz。多分だけど、9.2でpg_bulkloadをインストールするにはlibpqをダウングレードしないといけないっぽい。それは面倒なのでpostgresqlのバージョン9.4をインストールすることでバージョンを合わせることにした

$ sudo aptitude install postgresql-9.4
$ sudo aptitude install postgresql-server-dev-9.4

インストールの途中でlibpq-devは削除することになった。

make(成功)

バージョンを合わせたので、makeしてみると今度はライブラリが足らないというエラーが出た

$ sudo make
....
/usr/bin/ld: cannot find -lpam
/usr/bin/ld: cannot find -ledit
collect2: ld はステータス 1 で終了しました
make[1]: *** [pg_bulkload] エラー 1
make[1]: ディレクトリ `/***/pg_bulkload/bin' から出ます
make: *** [all] エラー 2

これはubuntuではlibpam-devとlibedit-devが足らないという意味らしいので、aptitudeからインストールした。

$ sudo aptitude install libpam-dev
$ sudo aptitude install libedit-dev

以上の作業でpg_bulkloadのmakeに成功した

$ sudo make
$ sudo make install

使ってみる

pg_bulkloadはbinフォルダ内にある。使い方は

  • 設定ファイルを書く
  • csvファイルを用意する
  • 実行する

となる。

設定ファイルを書く

設定ファイルの例はこんな感じ(下のコマンドの場合、example.ctlで保存しておく)、bin/data内にも例があるので参考になる。 この設定は

  • リダイレクトでcsvファイルを入力する。
  • リレーションをチェックする。リレーションにミスがある場合はエラーにする
  • タブ区切り
TYPE = CSV
INPUT = stdin
TABLE = table_name
CHECK_CONSTRAINTS = YES
DELIMITER = "   " #タブの場合
WRITER = DIRECT

コマンドはこんな感じ

$ ./pg_bulkload example.ctl --dbname db_name  < csv_name.csv
NOTICE: BULK LOAD START
NOTICE: BULK LOAD END
    0 Rows skipped.
    10 Rows successfully loaded.
    0 Rows not loaded due to parse errors.
    0 Rows not loaded due to duplicate errors.
    0 Rows replaced with new rows.

csvファイルはpsqlで\d table_nameで表示される順序にしておくこと。でないとパースエラーが出る。

順序が変わる場合

csvファイル内のフィールド順序をdb内の順序と違うものにしたい場合や、idなど、データを省略したい場合はフィルタを指定出来る。フィルタは

  • db内に関数を作る
  • 設定ファイルでフィルタを指定

で設定する。

フィルタの例

CREATE FUNCTION sample_filter(integer, text, text, real DEFAULT 0.05) RETURNS record
    AS $$ SELECT $1 * $4, upper($3) $$
    LANGUAGE SQL;

設定ファイル

TYPE = CSV
INPUT = stdin
TABLE = table_name
CHECK_CONSTRAINTS = YES
DELIMITER = "   " #タブの場合
WRITER = DIRECT
FILTER = sample_filter

出来てない点(追記予定)

  • MULTI_PROCESS = YESの時に認証失敗する件

参考: