チェックポイント処理は、定期的に共有バッファとディスクの間の整合性を取る。このときに共有バッファのデータが大量にディスクに書き込まれるため、システム全体のパフォーマンスが低下する。典型的な症状は、5分に1回データベースシステムの性能が低下するというものである。これは、デフォルトで5分に1回チェックポイントが行われるからである(負荷が高いシステムでは、もっと頻繁にチェックポイントが発生する)。
バッチ処理のようにスループットだけを気にする場合は、これは問題にならない。しかしWebアプリケーションのように、多数のユーザが会話的に処理を行うようなデータベースアプリケーションでは、5分に1回の割合でレスポンスが悪くなれば問題になる。そのとき以外はレスポンスが良いため、よけいギャップが気になるのだ。その結果、DB管理者に苦情が殺到するかもしれない。
このようなケースでは、5分に1回レスポンスが悪くなるよりは、性能が平均しているほうが好ましい。負荷分散チェックポイントは、この目的で導入された。
bgwriterとの比較
同じような目的を持った機能としてbgwriterというものがある。bgwriterはPostgreSQL 8.0で導入された機能で、定期的に共有バッファの内容をディスクに吐き出す。その結果、チェックポイントの負荷が減ると言うわけだ。
ではなぜbgwriterではダメなのか?
あるテーブルで頻繁に更新が行われていると、繰り返し同じ共有バッファのブロックに書き込みが行われる。bgwriterは定期的に書き込みのあったバッファ(ダーティバッファ)をその都度書き込む。bgwriterの設定を変更して、こまめにダーティバッファを書き込むようにすると、トータルのI/Oが増え、スループットが低下してしまう。
それに対して負荷分散チェックポイントでは、共有バッファを書き込むのはあくまでチェックポイントの時なので、スループットには影響を与えない。
負荷分散チェックポイントの使い方
負荷分散をチェックポイントを制御するために「checkpoint_completion_target」というパラメータが追加された。このパラメータのデフォルト値は0.5で、これによって次のチェックポイントまでの時間の約半分、すなわちデフォルトではチェックポイント開始から2分30秒の間にチェックポイント処理を完了するよう、チェックポイントの負荷を分散する。もちろんこれは負荷によっても変わるのであくまで目安程度に考えたほうがいい。
さらに負荷を分散させたい場合は、1.0までの範囲でcheckpoint_completion_targetを大きくすることができるが、0.9程度にとどめておくことが推奨されている。逆にチェックポイントの負荷をもっと大きくしてもよいのであれば、0.5よりも小さくできる。
checkpoint_completion_targetを必要以上に大きくすると、クラッシュリカバリ時に処理するWALログファイルが増えるので、時間がかかるというデメリットがある。したがって必要がなければcheckpoint_completion_targetをデフォルトから変更しないほうがよいだろう。
なおチェックポイントの状況は「log_checkpoints」を有効にすることで確認できる。
2007-09-24 21:35:45 JST LOG: checkpoint starting: time
2007-09-24 21:38:15 JST LOG: checkpoint complete: wrote 1693 buffers (55.1%);
0 transaction log file(s) added, 0 removed, 0 recycled; write=150.021 s, sync=0.014 s, total=150.062 s