今週はまっていること

相変わらずDB移行の部分です。
書籍をそのまままねて、

pg_dumpall -U username -h hostname -p port -d -D DBName > db.dump

とかやったのが悲劇の始まりでした。

psql -U username -h hostname -p port -f db.dump DBName

ってコマンドをうって週末帰路についたワケですが、週明けでも終わっていない…

INSERT 1 0

って具合にINSERTが行われ続けている…
まあいいやと思って取り敢えず、停止。

まあ色々と調べていて、ようやく原因が分かってきたような気がしてきたのでまとめてみる。

pg_dumpall に-dと-Dオプションがいらない?

http://www.postgresql.jp/document/pg803doc/html/app-pg-dumpall.html

  • d
    • inserts

データを(COPYではなく)INSERTコマンドとしてダンプします。これを行うとリストアが非常に遅くなります。これは主にPostgreSQL以外のデータベースにロードできるダンプを作成する時に役に立ちます。列の順序を変更した場合はリストアが失敗するかもしれないことに注意してください。更に低速になりますが、-Dオプションの方が安全です

  • D
    • column-inserts
    • attribute-inserts

データを明示的に列名を付けたINSERTコマンド(INSERT INTO table (column, ...) VALUES...)としてダンプします。これによりリストアは非常に遅くなります。これは主に、PostgreSQL以外のデータベースにロードできるダンプを作成する時に役に立ちます。

これを読む限り、バージョンが同じPostgres間のダンプ・リストアには必要無さそうなオプションでこいつが低速化させていたっぽい。
copyとinsertの違いがまだよく分かっていないんだけど、この当たりに改善のポイントはありそう。

標準出力への結果をdev/nullに捨てればよかった?

データ挿入結果が一々画面に出力されるのが終わらなかった原因っぽいかなぁと。
学生時代の研究でも、とりあえず標準出力を全てdev/nullに捨てるようにしただけで、某オープンソースのソフトウェアを利用した時の結果が出るまでの時間が大幅に改善されるなどした経験があるので、感覚的に大量の処理を行うときに標準出力がボトルネックなイメージがある。
というわけで、

psql -U username -h hostname -p port -f db.dump DBName > /dev/null

とすればいいのでは、という考え

ちなみに

データ挿入の途中でC-cで作業をやめたわけですが、データベースとしての機能は果たしてくれます。
(データはたりてないけど)
んでもって、一部のクエリに対して異常にレスポンスが遅くてなんでかなぁ、と考えていたんだけど、解決した。


ダンプファイルの構成が、

  1. テーブルの定義
  2. データ
  3. トリガー、ストアドプロシージャ、インデックス

という順番になっていて、
自分の場合は、データを流し込んでいる途中でやめたので、データベースとして必要最低限のテーブルと部分的なデータ、という状態になっていたと思われます。

んで、レスポンスの遅さの原因がインデックスが作られていなかったことかなぁ、と考えていて、実際、ダンプファイルの最後に記述されていたインデックスの部分をテーブルに流し込んだら、見事に高速に応答が帰ってくるようになりました。

今回学んだこと

  • pg_dumpall、pg_dumpの時に-dや-Dオプションを付けるとリストアが遅くなる
  • 標準出力を捨てた方がよさそう
  • インデックスは大事

以上