DB2 7 min read

Db2 INGEST の使い方と進捗確認 ― 既定のままでは失敗する2箇所

INGEST は Db2 の大量データ投入コマンドです。クライアント側で読み込み・変換・書き込みを別スレッドに分けて並列に流すため、IMPORT より桁違いに速く、投入中も表をほとんど止めません。

ただし既定の設定のままだと、1行も入らずに終わることがあります。この記事では基本形・進捗の見方・つまずく2箇所をまとめます。IMPORTLOAD を含めた選び分けは別記事にあります。

1. 基本形

入力ファイルの各フィールドを変数に割り当て、VALUES 句で投入先の列に対応させます。

db2 "INGEST FROM FILE data.csv FORMAT DELIMITED
(\$ID INT EXTERNAL, \$NAME CHAR(40), \$AMT DECIMAL(12,2) EXTERNAL)
INSERT INTO MY_TABLE VALUES (\$ID, \$NAME, \$AMT)"

検証環境(Db2 12.1.4)では、50万行の投入が 2.4〜2.6秒でした。同じデータを IMPORT で入れると54秒かかるので、20倍以上の差があります。投入中に他業務が止まったのは最大1.0秒でした。

2. 進捗を確認する

実行中のジョブは別セッションから確認できます。

[実行中のジョブ一覧]

db2 "INGEST LIST"

一覧に出る Ingest temp job ID1 などの数値)と Number of records processed が起点です。実行中のジョブが無ければ SQL2982W が返ります。

[詳細な進捗統計]

db2 "INGEST GET STATS FOR 1"

FOR に渡すのは Ingest temp job ID(数値)です。FOR ID 1 のように ID を挟むと SQL0104N になります。出力されるのは Overall ingest rate / Overall write rate / Current ingest rate / Current write rate / Total records の5項目です。Current 側が Overall 側を下回っていれば、その時点で書き込みが詰まっています。

3. 既定のままだと失敗する2箇所

■ リスタート表が無いと投入自体が始まらない

INGEST は既定でリスタート可能モードで動き、進捗を SYSTOOLS.INGESTRESTART に記録します。この表が無いと次のエラーで終わり、挿入は0行です。

SQL2957N The ingest operation failed to restart because the ingest utility
could not find the restart log table. Restart log table name:
"SYSTOOLS.INGESTRESTART". SQLSTATE=42704

「restart に失敗した」と読めるので、再開処理をしていないのに再開の話が出てくるため混乱します。新しい環境で INGEST を初めて使うときに踏みます。対処は表を作るか、リスタートを使わないかの2つです。

-- 表を作る。以後は既定のまま使えて、中断時の再開も効く
db2 "CALL SYSPROC.SYSINSTALLOBJECTS('INGEST','C',NULL,NULL)"

-- または、使い捨ての投入ならリスタートを切る(中断したら最初からやり直し)
db2 "INGEST FROM FILE data.csv FORMAT DELIMITED (...) RESTART OFF INSERT INTO MY_TABLE ..."

■ 行ロックが足りずに全件巻き戻る

投入先の表が既定の LOCKSIZE ROW のままだと、ロック要求が上限に達して SQL0912N で異常終了することがあります。検証環境(MAXLOCKS = 10)では50万行の投入で毎回落ち、止まる行数は実行のたびに違うのに、挿入行数はいずれも0でした。

-- 表ロックに切り替える
db2 "ALTER TABLE MY_TABLE LOCKSIZE TABLE"

LOCKLISTMAXLOCKS を増やす手もあります。どちらを取るかは、投入中に他業務を通したいかで決めます。

4. CPU 負荷を抑える

書き込みスレッド(フラッシャー)数を制限すると、CPU スパイクを抑えられます。設定は投入文の中ではなく別のコマンドとして、投入の前に実行します。投入文の中に SET を書くと SQL0104N になります。パラメーター名も num_flushers ではなく num_flushers_per_partition です。

db2 "INGEST SET num_flushers_per_partition 2"
db2 "INGEST FROM FILE data.csv FORMAT DELIMITED (...) INSERT INTO MY_TABLE ..."

INGEST SET は構文の判定がクライアント側で完結するので、インスタンスが停止していても通ります。パラメーター名の確認だけなら db2start は要りません。

5. IMPORT・LOAD との違い

よく「INGEST は速いのでログにも優しい」と言われますが、実測では違いました。50万行あたりのログ消費量は IMPORT同じ1,145ページで、LOAD だけが9ページ(127分の1)です。INGEST も1行ずつログに書くためで、速さの差は書き込み方から来ています。

ログ量・投入中の可用性・投入後の表スペース状態で3方式を比べた逆引きは別記事にまとめています。

Db2のデータ投入中に他業務が固まる ― IMPORT・INGEST・LOADの逆引き

関連: Db2「SQL0964C トランザクションログがいっぱいです」の原因を切り分けるDb2「SQL0668N 操作は許可されません」を理由コードで切り分ける

LOAD失敗の後始末や制限状態からの復帰のような、マニュアルを引いても手順の順序までは分からない場面を、本書 第12章「現場の難題・解決集」に実例で集めました。

現場で引ける Db2 の教科書

現場で引ける!Db2実践エンジニア・バイブル

Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。

アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集

Zennで読む(¥2,000)→