PostgreSQLに限らず、大抵のデータベースソフトウェアは、磁気ディスクなどの永続ストレージ上のデータを、必要に応じてメモリ上に置くことで高速な読み書きを実現しています。このとき、バッファリングという仕組みが使われます。
最初にアクセスするときには、ストレージから読み込みますが、それをメモリ上のバッファーに載せておき、次に同じデータにアクセスするときにはバッファー上にあるものを使うので、メモリに対するアクセスだけで済むという仕組みです。
使っているうちに、よくアクセスがあるデータほどバッファーに載っている状態になっていき、より効率的に動作するようになっていきます。
さて、この仕組みでは、サーバーマシンを起動した直後であったり、PostgreSQLサーバープロセスを起動した直後であったりすると、ストレージからの読み取りを実行する頻度が高くなり、アクセスが遅くなります。
そこで、サービス提供時点のアクセスで応答が遅くならないように、事前にウォーミングアップする対策が行われます。例えば、朝9時になるとアクセスが集中するシステムを夜間メンテナンスで再起動したなら、翌朝9時のアクセス集中時にはバッファーにヒットするように、再起動後にダミーのSELECTコマンドを実行しておくウォーミングアップを実施しておくのです。
PostgreSQL 9.4では、このウォーミングアップ専用の拡張モジュールpg_prewarmが付属します。
以下のようにCREATE EXTENSIONコマンドで拡張モジュールをインストールした上で(拡張モジュールの導入方法は前回記事を参照)、pg_prewarm関数を実行すると、指定したテーブルt1のデータを共有バッファーに載せることができます。関数の戻り値はバッファーに載せることができたページ数(1ページは8KB)です。
db1=# CREATE EXTENSION pg_prewarm; db1=# SELECT * FROM pg_prewarm('t1'); pg_prewarm ------------ 8334 (1 row)
従来行われていたダミーのSELECTコマンドを使う方法に対して、pg_prewarmを使ったウォーミングアップの優位点は、「確実にバッファーに載せてくれること」にあります。
最近のPostgreSQLのデータベースエンジンは賢くなっていて、テーブルをVACUUMしたり、「SELECT * FROM t1」のような命令を実行したりした場合には、あまりバッファーに載せてくれません。この挙動は、長期の運用を経てよく使うデータが選別されてバッファーに載っている最適化した状態を、一つのコマンドによって全て上書きしてしまい、パフォーマンスが劣化してしまうのを防ぐためです。最適化には優れていますが、一方で、意図してバッファーに載せたい場合には不便でした。
一方のpg_prewarm拡張モジュールの場合は、バッファーに載せることを目的とした専用関数なので、意図通りに可能な限りバッファーに載せてくれます。
なお、pg_prewarmでは省略可能な第2引数から第5引数までを指定して、PostgreSQLバッファーではなくOSのバッファーに載せるようにする、データの一部だけを対象とする、などの細かな動作の調整もできます(下記表参照)。
オプション引数 | 指定内容 |
---|---|
第2引数 | 'buffer' 'read' 'prefetch'のいずれかを指定 (readでOSバッファーに載せる、prefetchはOSに示唆するだけの弱い指定) |
第3引数 | 'main' 'fsm' 'vm'のいずれかを指定 (mainがテーブルのデータ本体、fsmとvmは管理情報領域) |
第4引数 | 始点ページ番号 |
第5引数 | 終点ページ番号 |
表1 pg_prewarmの引数と指定内容
Copyright © ITmedia, Inc. All Rights Reserved.