名前
pg_bulkload -- 一定の制約条件の下で大量のデータを高速にロードするためのプログラムです。
概要
pg_bulkload [ OPTIONS ] [ controlfile ]
説明
pg_bulkload は、大量のデータを高速に投入する目的のためのツールです。
データベース制約のチェックの有無や、エラーデータをスキップして投入を継続するか否かを制御でき、入力データに応じた柔軟なデータができます。
たとえば、あるデータベースに格納されている情報を別のデータベースへ移送するような状況では、データの整合性は既に確認済みですので、細かなチェックは省いてとにかく高速にデータをロードできます。
一方、別のツールの出力など整合性が怪しい場合には、制約をチェックしながら投入できます。
pg_bulkload は元々は PostgreSQL 組み込みのデータロード用コマンドである COPY を上回る性能を目指して開発されました。
バージョン 3.0 はさらに入力データの検証機能やフィルタによる変換機能を備え、ETL ツールの T (Transform) と L (Load) を強力にサポートします。
使用例
pg_bulkload を利用するユーザが直接扱うプログラムは以下の2つです。
postgresql スクリプト
pg_ctl コマンドのラッパコマンドで、PostgreSQL サーバを起動・停止するプログラムです。
postgresql スクリプトの内部で pg_ctl コマンドを呼び出しています。
また、pg_bulkload によるロード中にサーバがダウンした場合、pg_bulkload コマンドを呼び出して自動的に独自のリカバリを行う機能を持っています。
pg_bulkload を利用する場合、必ずこの postgresql スクリプトを使用してください。
下記の "使用上の注意と制約" を必ず読んでください。
特に、下記の利用方法では注意する必要があります。
- pg_bulkload を DIRECT モードまたは PARALLEL モードで使うとき (WAL 書き込みをスキップします: デフォルトの設定です)
pg_bulkload
データのロードを行うために呼び出すプログラムです。
内部で pg_bulkload() ユーザ定義関数を呼び出して、PostgreSQL サーバ内で実際のロード処理を行います。
pg_bulkload() ユーザ定義関数は、pg_bulkload のインストール時に作成されます。
次の 3 ステップにより、pg_bulkload でロードすることが可能です。
- ロードに関する設定を記述する制御ファイルを作成し、ロード対象のテーブル名、入力ファイルのパスなどを指定します。
"sample_csv.ctl" もしくは "sample_bin.ctl" を参考にして下さい。
- $PGDATA/pg_bulkload ディレクトリが存在することを確認してください。そのディレクトリにはロードステータスファイルが作成されます。
- 制御ファイルを引数としてコマンドを実行します。
$ pg_bulkload sample_csv.ctl
オプション
pg_bulkload では、下記のコマンドライン引数を指定できます。
接続オプション
PostgreSQL に接続するためのパラメータです。
-
-d DBNAME
--dbname=DBNAME
- ジョブを行うデータベース名を指定します。
データベース名が指定されておらず、--all も指定されていない場合、データベース名はPGDATABASE 環境変数から読み取られます。
この変数も設定されていない場合は、接続時に指定したユーザ名が使用されます。
- -h HOSTNAME
--host=HOSTNAME
- サーバが稼働しているマシンのホスト名を指定します。ホスト名がスラッシュから始まる場合、Unix ドメインソケット用のディレクトリとして使用されます。
- -p PORT
--port=PORT
- サーバが接続を監視する TCP ポートもしくは Unix ドメインソケットファイルの拡張子を指定します。
- -U USERNAME
--username=USERNAME
- 接続するユーザ名を指定します。
- -W
--password
- データベースに接続する前に、pg_bulkload は強制的にパスワード入力を促します。
サーバがパスワード認証を要求する場合 pg_bulkload は自動的にパスワード入力を促しますので、これが重要になることはありません。
しかし、pg_bulkload は、サーバにパスワードが必要かどうかを判断するための接続試行を無駄に行います。
こうした余計な接続試行を防ぐために -W の入力が有意となる場合もあります。
一般オプション
- -e
--echo
- サーバに送信するSQLを表示します
- -E
--elevel = LEVEL
- ログ出力レベルを設定します。
- --help
- ヘルプを表示し、終了します
- --version
- バージョン情報を出力し、終了します
ロードオプション
ロード内容を指定するためのパラメータです。
-
-i INFILE
--infile=INFILE
- ロード対象の入力データのパスを指定します。
相対パスで指定した場合は、pg_bulkload コマンド実行時のカレントディレクトリが基準となります。
相対パスで指定できること以外は、制御ファイルの設定項目の "INFILE" と同じです。
-
-l LOGFILE
--logfile=LOGFILE
- ロード処理の結果を記録するログファイルのパスを指定します。
相対パスで指定した場合は、pg_bulkload コマンド実行時のカレントディレクトリが基準となります。
-
-P PARSE_BADFILE
--parse-badfile=PARSE_BADFILE
- 入力データのパース時に見つかった不良レコードを記録するBADファイルのパスを指定します。
相対パスで指定した場合は、pg_bulkload コマンド実行時のカレントディレクトリが基準となります。
-
-u DUPLICATE_BADFILE
--duplicate-badfile=DUPLICATE_BADFILE
- インデックスメンテナンス処理で見つかった一意制約違反の不良レコードを記録するBADファイルのパスを指定します。
相対パスで指定した場合は、pg_bulkload コマンド実行時のカレントディレクトリが基準となります。
-
-o "key=val"
--option="key=val"
- 制御ファイルで指定可能な設定項目を指定します。複数の設定項目を指定する場合は、"-o" または "--option" を複数指定します。
制御ファイル
pg_bulkload では、データのロード方法を制御ファイルで指定できます。制御ファイルはクライアント側に配置してください。相対パスで指定可能です。相対パスで指定した場合は、pg_bulkload コマンド実行時のカレントディレクトリが基準となります。省略する場合は pg_bulkload コマンドのコマンドライン引数でロード方法を指定してください。
制御ファイルには、下記の設定項目を指定できます。pg_bulkload パッケージに含まれる sample_csv.ctl や sample_bin.ctl もあわせて参照してください。
なお、"#"以降はコメントとして無視されます。
フォーマット共通の設定項目
- TABLE = [ schema_name. ] table_name
-
ロード先のテーブルを指定します。
schema_name を省略した場合は、search_path に指定した検索パスから見つかったテーブルを使用します。
必須のパラメータです。
- TYPE
-
入力データのタイプを以下のいずれかで指定します。
必須のパラメータです。
- CSV : CSV フォーマットのデータを読み込みます。
- BINARY (FIXED) : 固定長フォーマットのデータを読み込みます。
- FUNCTION : 関数が返した行セットを読み込みます。
このタイプを指定した場合は、INFILE に関数呼び出し式を指定してください。
- INFILE
-
ロードの入力データソースを指定します。
必須のパラメータです。
使用する入力データに応じて、以下のように指定します。
- サーバ上のファイル :
サーバ上でのパスで入力ファイルのパスを指定します。
PostgreSQL プロセスを起動したユーザにファイルに対する読み込み権限を与える必要があります。
「TYPE=CSV」および「TYPE=BINARY」と指定した場合のみ使用可能です。
- pg_bulkload コマンドの標準入力 :
「INFILE=stdin」と記述すると、pg_bulkload コマンドの標準入力から入力データを読み取ります。
入力ファイルとデータベースが異なるサーバに配置されている場合には、こちらの形式を使用してください。「TYPE=CSV」および「TYPE=BINARY」と指定した場合のみ使用可能です。使用例を以下に示します。
$ pg_bulkload csv_load.ctl < DATA.csv
- SQL関数の結果:入力データを返す SQL 関数の呼び出し式を指定します。
この形式で使用するSQL関数は、SETOF RECORD を返す必要があります。
「TYPE=FUNCTION」と指定した場合のみ使用可能です。
以下の使用例では組み込みの関数を指定していますが、ユーザ定義関数を指定することも可能です。
ただし、大量のデータをロードする場合には PL/pgSQL ではなく C言語での関数作成を推奨します。
ストリーミング・ロードを行うため SFRM_ValuePerCall モードで実装される必要があるためです。
TABLE = sample_table
TYPE = FUNCTION
WRITER = DIRECT
INFILE = generate_series(1, 1000) # 1から1,000の連番をロードする
...
- SKIP|OFFSET = n
-
先頭から何行をスキップするかを指定します。
デフォルトは 0 です。
ただし「TYPE=FUNCTION」と指定した場合は無視されます。
- LIMIT|LOAD = n
-
ロード行数を指定します。
デフォルトは指定なし (全行ロード) です。
「TYPE=FUNCTION」と指定した場合でも使用可能です。
- ENCODING
-
入力データのエンコーディングを指定します。
入力データのエンコーディングと DB サーバのエンコーディングが違う場合に指定すると、エンコーディング変換を行います。
入力データのエンコーディングと DB サーバのエンコーディングが同じ場合に指定すると、エンコーディングの正当性チェックを行います。
入力データのエンコーディングの正当性が保証されていて、かつ DB エンコーディングと同じ場合は、この設定項目を指定しないことで、高速にロードできます。
デフォルトでは、エンコーディングの正当性チェックも変換も行いません。
ただし「INFILE=stdin」と指定した場合のデフォルトは client_encoding の値を使用します。
-
エンコーディングの変換は、client_encoding を扱うのと同じ方式で処理されます。
有効なエンコーディングについては Built-in Conversions を参照してください。
設定値と処理内容の関係を以下の表に示します。
-
|
DB エンコーディング |
SQL_ASCII |
SQL_ASCII 以外 |
ENCODING |
指定なし |
正当性チェックも変換もしない |
正当性チェックも変換もしない |
SQL_ASCII |
正当性チェックも変換もしない |
正当性チェックのみ |
SQL_ASCII 以外で DB エンコーディングと同じ |
正当性チェックのみ |
正当性チェックのみ |
SQL_ASCII 以外で DB エンコーディングと違う |
正当性チェックのみ |
エンコーディング変換 |
- FILTER = [ schema_name. ] function_name [ (argtype, ... ) ]
-
入力データを変換するユーザ定義関数 (FILTER 関数) を以下の形式で指定します。
argtype は省略可能ですが、関数を一意に特定できない場合はエラーになります。
指定しない場合は、入力データの変換を行いません。
FILTER 関数の作り方は FILTER 関数の作り方に示しています。
-
FILTER オプションは、「TYPE=FUNCTION」を指定した場合は無視されます。
また、CSV フォーマット固有の設定項目の FORCE_NOT_NULL と FILTER の両方を指定した場合はエラーになります。
- CHECK_CONSTRAINTS = YES|NO
-
CHECK 制約を適用するかどうかを指定します。
YES の場合は CHECK 制約を適用し、NO の場合は CHECK 制約を適用しません。
デフォルトは NO です。
- ON_DUPLICATE_KEEP = NEW|OLD
- 一意制約違反のレコードが存在した場合の挙動を以下のいずれかで指定します。デフォルトは OLD です。
- NEW : 入力データに存在するレコードを残し、既にテーブルに存在していたレコードの内容を BAD ファイルに書き出します。入力データ同士で一意制約違反となるレコードが存在していた場合は、ファイルの先頭側のレコードを残します。
- OLD : 既にテーブルに存在するレコードを残し、入力データに存在するレコードを BAD ファイルに書き出します。
- PARSE_ERRORS
-
パース処理、エンコーディングチェック、エンコーディング変換、FILTER 関数の実行、CHECK 制約適用および非 NULL 制約適用時に発生したエラーの許容件数を指定します。エラーを許容された不良データはロードされず、PARSE BADFILE に記録されます。
デフォルトは 0 です。
発生したエラーの件数がこの値を超えた場合は、その時点でコミットして残りの入力データのロード処理をキャンセルします。
エラーを1件も許容しない場合は 0 を、全てのエラーを許容する場合は -1 を指定します。
- DUPLICATE_ERRORS
- 一意制約違反の許容件数を指定します。エラーを許容された一意制約違反のレコードはロードされず、DUPLICATE BADFILE に記録されます。
デフォルトは 0 です。
一意制約に違反するレコードの数がこの値を超えた場合は、その時点でロールバックしてロード処理をキャンセルします。
エラーを1件も許容しない場合は 0 を、全てのエラーを許容する場合は -1 を指定します。
- WRITER = DIRECT|BUFFERED|PARALLEL
-
ロード方式を以下のいずれかで指定します。デフォルトは DIRECT です。
- DIRECT : 高速ですが特殊なリカバリ手順が必要です。WALをスキップし、共有バッファも汚しません。
- BUFFERED : 特殊なリカバリは不要です。ただし、WALを書き、共有バッファも汚します。
- PARALLEL : 基本的には DIRECT と同じですが、データの読み取りと書き出しをそれぞれ異なるプロセスで実行します。
- LOGFILE = path
-
処理内容を記録するログファイルのパスを指定します。
デフォルトは $PGDATA/pg_bulkload/<タイムスタンプ>_<DB名>_<スキーマ名>_<テーブル名>.log です。
- PARSE_BADFILE = path
-
パース処理、エンコーディングチェック、エンコーディング変換、FILTER 関数の実行、CHECK 制約適用および非 NULL 制約適用時に見つかった不良レコードを記録するBADファイルのパスを指定します。
このファイルには、入力ファイルと同じ形式(CSVまたは固定長)で記録されます。
デフォルトは $PGDATA/pg_bulkload/<タイムスタンプ>_<DB名>_<スキーマ名>_<テーブル名>.bad.<入力ファイルの拡張子> です。
- DUPLICATE_BADFILE = path
-
一意制約違反の不良レコードを記録する BAD ファイルのパスを指定します。
このファイルには、入力ファイルの形式によらず CSV 形式で記録されます。
デフォルトは $PGDATA/pg_bulkload/<タイムスタンプ>_<DB名>_<スキーマ名>_<テーブル名>.dup.csv です。
- TRUNCATE = YES|NO
-
YES の場合は、データロードの前にテーブルから全ての行を削除します。
内部的には SQL の TRUNCATE 相当の処理を行っています。
NO の場合は削除しません。デフォルトは NO です。
- VERBOSE = YES|NO
-
YES の場合は、入力データのパース時に見つかった不良データのエラーログおよび一意制約違反のエラーログをサーバログにも出力します。
NO の場合はサーバログに出力しません。デフォルトは NO です。
CSV フォーマット特有の設定項目
- DELIMITER
- デリミタを指定します。
デフォルトは「,」です。ASCII 文字(1バイト文字)でなければなりません。
- QUOTE
- 引用符を指定します。
デフォルトは「"」です。ASCII 文字(1バイト文字)でなければなりません。
- ESCAPE
- エスケープ文字を指定します。
デフォルトは「"」です。ASCII 文字(1バイト文字)でなければなりません。
- NULL
- NULL 値を表す文字列を指定します。
デフォルトは空文字列(長さ 0 の文字列)です。
- FORCE_NOT_NULL
- 入力ファイル中の表現が NULL 値文字列であっても NULL として扱わないカラムを 1行 1カラム名で指定します。
複数個指定することが可能です。
フォーマット共通の設定項目の FILTER と FORCE_NOT_NULL の両方を指定した場合はエラーになります。
固定長フォーマット特有の設定項目
- COL = type [ (size) ]
-
-
入力ファイルのカラムフォーマットを型と開始位置とサイズで指定します。
サイズは開始位置と終了位置の組み合わせで指定することもできます。
型には以下のいずれかを指定します。
CHAR と VARCHAR の場合、入力データがテキストであることを表します。
それ以外の場合はバイナリであることを表します。
バイナリはロード先のサーバのエンディアンで扱われます。
- CHAR : 末尾の空白を取り除きます。サイズを指定する必要があるため、「COL=CHAR」と指定するとエラーになります。
- VARCHAR : 末尾の空白が残します。サイズを指定する必要があるため、「COL=VARCHAR」と指定するとエラーになります。
- SMALLINT : 指定できるサイズは 2 のみです。
- INTEGER : 指定できるサイズは 2 と 4 と 8 です。型のサイズは 4 です。
- BIGINT : 指定できるサイズは 8 のみです。
- UNSIGNED SMALLINT : 指定できるサイズは 2 のみです。
- UNSIGNED INTEGER : 指定できるサイズは 2 と 4 です。型のサイズは 4 です。
- FLOAT : 指定できるサイズは 4 のみです。
- DOUBLE : 指定できるサイズは 4 と 8 です。型のサイズは 4 です。
上記の型に対して、開始位置とサイズを以下のように指定します。
- TYPE(S+L) : レコード先頭から数えて S バイト目から L バイト分をカラムデータとみなします。
- TYPE(L) : 直前のカラムに続く L バイト分をカラムデータとみなします。
- TYPE : 直前のカラムに続く型ごとの長さ分をカラムデータとみなします。
- TYPE(S:E) : レコード先頭から数えて S バイト目から E バイト目までをカラムデータとみなします。
上記の他に「COL=L」で指定できます。この指定方法は「COL=CHAR(L)」と同じで、後方互換のために残されています。
- PRESERVE_BLANKS = YES|NO
-
カラムフォーマットを「COL=N」で指定した場合に、カラムデータの末尾の空白を残すかどうかを指定します。
複数個指定することが可能で、PRESERVE_BLANKS を指定した行以降の「COL=N」の扱いを変更します。YES の場合、「COL=N」を「COL=VARCHAR(N)」とみなし、末尾の空白を残します。NO の場合、「COL=CHAR(N)」とみなし、末尾の空白を取り除きます。
デフォルトは NO です。
- STRIDE = n
-
1 行あたりのバイト数を指定します。
指定しない場合は COL パラメータから計算された値を使います。
行の末尾にロードには使用しないパディングが含まれる場合にのみ明示的な指定が必要です。
環境変数
設定パラメータです。
-
PGDATABASE
PGHOST
PGPORT
PGUSER
- デフォルトの接続パラメータです。
また、このユーティリティは、他のほとんどの PostgreSQL ユーティリティと同様、libpq でサポートされる環境変数を使用します。詳細については、環境変数の項目を参照してください。
使用上の注意と制約
ダイレクトロードで使用する場合
ダイレクトロードで使用する場合 (WRITER=DIRECT または WRITER=PARALLEL)、以下のことに注意しなければなりません:
PostgreSQL 起動手順
pg_bulkload がクラッシュし、.loadstatus ファイルが $PGDATA/pg_bulkload に残っていた場合、データベースは pg_bulkload 独自のリカバリ手順によってリカバリする必要があります。これは "pg_bulkoad -r" コマンドを "pg_ctl start" より前に実行することにより行います。PostgreSQL の起動・停止を postgresql スクリプトにより行うことで、このリカバリをし忘れることを防ぎます。postgresql スクリプトは内部的に "pg_bulkload -r" を実行し、続けて "pg_ctl start" を行っています。そのためダイレクトロードの利用環境下では、pg_ctl を直接使わずに、postgresql スクリプトを利用することをお勧めいたします。
PITR
WAL を残さないために、PITR によるアーカイブログリカバリは利用できません。もし PITR を利用する場合には、ロード終了後に対象のデータベースのバックアップを取ってください。
$PGDATA/pg_bulkload 内のロードステータスファイル
$PGDATA/pg_bulkload ディレクトリ中のロードステータスファイル (*.loadstatus) は絶対に削除してはいけません。 pg_bulkload のリカバリのために必ず必要になるからです。
kill -9は使わない
pg_bulkload を "kill -9" を使って停止させるのはできる限りやめてください。もし実行すると postgresql スクリプトによるリカバリが実行されます。
FILTER 関数の作り方
以下に FILTER 関数を作る際の注意点や制約を示します。
- 入力データの 1 行分のデータが、FILTER 関数の引数として渡されます。
- 関数を実行した結果、エラーが発生した場合は、そのレコードはロードされずに PARSE BADFILE に記録されます。
- FILTER 関数の返り値は record 型またはテーブル型で作成する必要があります。また、関数の実行によって実際に返されるレコードのデータ型は、ロード対象のテーブルの列定義と一致する必要があります。
- 関数が NULL を返した場合は、全ての列が NULL のレコードをロードします。
- 引数にデフォルト値を持つ関数に対応しています。入力データの列数が関数の引数の数に満たない場合に、デフォルト値が適用されます。
- 可変長引数を取る関数 (VARIADIC 引数を持つ関数) には対応していません。
- 集合を返す関数 (SETOF 修飾子を持つ関数) には対応していません。
- 多様SQL関数 (多様型を引数に持つ関数) には対応していません。
- FILTER 関数を実装する言語は問いません。SQL、C 言語、手続型言語のどの言語で実装しても構いません。
- FILTER と FORCE_NOT_NULL 設定項目はどちらか一方しか指定できないため、FILTER 関数を使用したい場合に FORCE_NOT_NULL の機能が必要な場合は、 FILTER 関数に FORCE_NOT_NULL 機能を実装してください。
FILTER 関数の前後の処理については
内部構成に示しています。
作成例を以下に示します。
CREATE FUNCTION sample_filter(integer, text, text, real DEFAULT 0.05) RETURNS record
AS $$ SELECT $1 * $4, upper($3) $$
LANGUAGE SQL;
その他の制限
デフォルトでは、ロード時のデータの整合性は、一意制約と非 NULL 制約およびプライマリキー制約のみ適用します。CHECK 制約を適用する場合は、"-o" オプション、"--option" オプションまたは制御ファイルで「CHECK_CONSTRAINTS=YES」と指定してください。外部キー制約は適用しません。 入力データセットの妥当性についてはユーザにより保証してください。
詳細
全体構成
以下に通常ファイルを入力とした場合の構成を示します。
以下に pg_bulkload コマンドの標準入力を入力とした場合の構成を示します。
以下に SQL 関数の結果を入力とした場合の構成を示します。
内部構成
以下に pg_bulkload() ユーザ定義関数の内部構成を示します。
ファイル構成
pg_bulkload を利用するユーザが直接扱うプログラムは以下の二つです。
- pg_bulkload
- データのロードを行うために呼び出すプログラムです。内部で pg_bulkload() ユーザ定義関数を呼び出して、PostgreSQL サーバ内で実際のロード処理を行います。pg_bulkload() ユーザ定義関数は、pg_bulkload のインストール時に作成されます。
- postgresql スクリプト
- pg_ctl コマンドのラッパコマンドで、PostgreSQL サーバを起動・停止するプログラムです。postgresql スクリプトの内部で pg_ctl コマンドを呼び出しています。また、pg_bulkload によるロード中にサーバがダウンした場合、pg_bulkload コマンドを呼び出して自動的に独自のリカバリを行う機能を持っています。
pg_bulkload 利用環境下では、できる限りこの postgresql スクリプトを使用してください。特に DIRECT モードまたは PARALLEL モードで使う場合に重要です。
インストール方法
pg_bulkload のインストールは、標準の contrib モジュールと同様です。
環境設定
pg_bulkload をインストールする前に以下を実行しているものとします。
- PostgreSQL がインストールされていること
- PostgreSQL のインストールで使用したソースツリーが存在していること
- initdb を実行し、データベースクラスタが作られていること
ソースコードからのインストール
pgxs を使ってビルドできます。
$ cd pg_bulkload
$ make USE_PGXS=1
$ su
$ make USE_PGXS=1 install
pg_bulkload 用の関数を登録します。
$ postgresql start
$ psql -f $PGSHARE/contrib/pg_bulkload.sql database_name
RPM パッケージからのインストール
通常の RPM パッケージのインストール手順と同様です。
pg_bulkload インストール前に postgresql-server がインストールされていることを確認してください。
次のコマンドで pg_bulkload をインストールします。
# rpm -ivh pg_bulkload-<version>.rpm
以下のコマンドでインストールされたかどうかを確認できます。
# rpm -qa | grep pg_bulkload
また、以下のコマンドで、各ファイルがどこにインストールされたかを確認できます。
# rpm -qs pg_bulkload
pg_bulkload 用の関数を登録します。上記 rpm -qs の実行結果で表示される pg_bulkload.sql のパスを確認してください。以下の例では環境変数 $PGSHARE を利用しています。
$ postgresql start
$ psql -f $PGSHARE/contrib/pg_bulkload.sql database_name
動作環境
- PostgreSQLバージョン
- PostgreSQL 8.3, 8.4, 9.0
- OS
- RHEL 5.3, Fedora 12, Windows XP
関連項目
COPY