◆ VACUUM の実行
PostgreSQL ドキュメント定常的なデータベース保守作業の俺様要約
- PostgreSQL はレコードが更新/削除されても物理削除は行わない
- これは
VACUUM
で行うので定期的な実行が必要 - 更新頻度の高いテーブルほど頻繁に
VACUUM
のすること - 普通の
VACUUM
とVACUUM FULL
の 2 種類がある - 普通の
VACUUM
は使われていない領域に再利用可能なマークを付ける - 普通の
VACUUM
は不要領域がファイルの最後でない限りファイル縮小は行わない - 普通の
VACUUM
は他のトランザクションにほとんど影響しない VACUUM FULL
は不要領域の占有領域を削除しファイルを縮小するVACUUM FULL
は他のトランザクションに与える影響も甚大- 一般的には1日1回普通の
VACUUM
をしておけばよい - 全レコードを削除する場合は
TRANCATE
を使えばVACUUM
する必要がない - トランザクション ID は 32 ビットで周回する
- トランザクション ID が周回が発生するとデータ損失が起きる
- 7.2 以降は 10 億トランザクション発行する前に
VACUUM
が必要 - 残りトランザクション数が1000万を下回ると警告が出る
- 残りトランザクション数が100万を下回ると発行が出来なくなる
俺様の理解
- Java の Gabage Collection で例えるなら普通の
VACUUM
= Mark & Swept、VACUUM FULL
= Compact 、Windows で例えるならVACUUM FULL
= デフラグ - 定期処理は1日1回普通の
VACUUM
だけで十分 (VACUUM FULL
はディスク容量を見ながらの不定期で良い?)
◆ バックアップとリストア
PostgreSQL ドキュメントバックアップとリストアの俺様要約
pg_dump
は運用中の実行が可能pg_dump
はテーブル構成や全レコードを SQL で出力する- 出力した SQL を
psql
に流し込むと再構築が可能 - ユーザ等、クラスタまとめてバックアップしたい場合は
pg_dumpall
を使用 - ファイルが大きくなる場合はパイプで圧縮すなり分割するなり
- 単純なファイルコピーによるバックアップは postgreSQL の完全停止が必要 (全切断だけではNG)
- ポイントインタイムリカバリ (PITR) という JFS やロールフォーワードのような障害復旧機構がある
- RITR は WAL ファイルにログ (ジャーナル) を記録している
- WAL ファイルを累積的に保管するだけで任意の時点でのスナップショットが再現できる
- WAL ファイルをバックアップ機で再生すればホットスタンバイを実現できる
俺様の理解
- 小規模システムなら
pg_dump
の定期バックアップで十分 pg_dump
の定期バックアップが現実的でない大規模システムは WAL ファイルで
さらに続きである。これで完結である (ことを願う…)。
まずは観測から。
何とかなりそう! ヽ(´ー`)ノ
PostgreSQL で大きなバイナリを扱うには、今まで試した BYTEA 型を使用するほかに OID 型を使用する方法がある。BYTEA 型がバイナリそのものをテーブルに格納するのに対し、OID 型はオブジェクトの ID のみを格納し、実体のバイナリはどこか別のところに保存される (PostgreSQL の場合はシステムカタログのどこかに入るらしい)。
元々 BLOB がロケーション ID やオフセット、長さなどを使って巨大なバイナリを扱うための手段だということを考えれば、むしろこの OID 型を BLOB と呼ぶ方が自然だ (ちなみに商用データベースの方は実体をテーブルスペース外の別ファイルにするか VARBINARY と同様にテーブル内に入れるかなど、きめ細かな構成を選択できるが)。
PostgreSQL の JDBC ドキュメントを参照すると、Java で OID 型を扱うには "LargeObject API" なるものを使わなければならいように見えるが、実は JDBC の java.sql.Blob と互換性のある方法で取り扱えるようになっているようだ。正にこっちが PostgreSQL 的 BLOB なのである。
ネットを検索してみる限り、BYTEA 型を扱うサンプルはいくつか見つかるものの、OID 型を java.sql.Blob で扱う Java チュートリアルはほとんど無いようだ (これが日本語初か?)。なので今回はチュートリアルっぽくまとめてみる。例によってコード簡略化のためリソースのクローズや変数宣言等は省略。
出た! (;´ー`)y─┛~~
前回、InputStream を使って巨大データを BYTEA 型カラムに格納出来たわけだが、今度は保存した内容を取り出すタイミングで再び OutOfMemoryError が姿を現した。
なんだかすごーく嫌な予感がするのだが… とりあえず 8.1 ドライバのソースでも見てみるか。
public InputStream getBinaryStream(int columnIndex) |
. .: : : : : : : : :: :::: :: :: : :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
. . : : : :: : : :: : ::: :: : :::: :: ::: ::: ::::::::::::::::::::::::::::::::::::::
. . .... ..: : :: :: ::: :::::: :::::::::::: : :::::::::::::::::::::::::::::::::::::::::::::
Λ_Λ . . . .: : : ::: : :: ::::::::: :::::::::::::::::::::::::::::
/:彡ミ゛ヽ;)ー、 . . .: : : :::::: :::::::::::::::::::::::::::::::::
/ :::/:: ヽ、ヽ、 ::i . .:: :.: ::: . :::::::::::::::::::::::::::::::::::::::
/ :::/;;: ヽ ヽ ::l . :. :. .:: : :: :: :::::::: : ::::::::::::::::::
 ̄ ̄ ̄(_,ノ  ̄ ̄ ̄ヽ、_ノ ̄ ̄ ̄ ̄
PostgreSQL 7.4.11 (JDBC 3 Driver 7.4.215) の BYTEA (BLOB) 型カラムにファイルの内容を放り込もうと思ったのだが、ファイルサイズが数十MB になると例外が発生してしまうようだ。
java.lang.OutOfMemoryError: Java heap space |
例外が起きなくてもディスクスワップが多発しているようだし、ひょっとしてファイルの全バイナリから巨大な SQL でも組み立てているのだろうか? 今回はそこらへんをちょっと突っ込んで調べてみようと思う。
PostgreSQL 8.0/8.1 の Windows 版をインストールする時、デフォルトの EUC_JP 以外の文字セット (UNICODE, UTF-8 など) を選択してはならない。
インストールで選択するのは initdb の際に用いられる文字セットなのだが、デフォルト以外を選択すると日本語で検索できなくなったりするのだ。ちなみに Linux 版だと initdb で UNICODE を選択しても問題はない。
なお CREATE DATABASE で指定する文字セットを EUC_JP 以外にして問題あるかは不明。