性能の改善点の2番目は、同期スキャン(Synchronized Scan)だ。これは、複数のセッションが比較的大きなテーブルを同時に順スキャン(インデックスを使わずテーブル全体を読み出すアクセス方法)する際の性能を上げる効果がある。

もともと順スキャンはI/Oを大量に発生させるので、負荷が大きい。それが複数同時に実行されれば、さらに大きな負荷となり、データベースの性能が極端に下がってしまうことになる。もちろんインデックスをうまく使って順スキャンを避けることができればよいのだが、問い合わせによってはそうもいかないこともある。

よく考えてみると、最初にテーブルをスキャンしたときはしょうがないが、2番目以降のセッションは、すでに共有バッファにデータが乗っているのだから、I/Oなしに素早くアクセスできるのではないか?

もしもテーブルが小さくて全体が共有バッファに乗る場合には、実際そのようにPostgreSQLは動作するので問題ない。問題は、テーブルが大きすぎて共有バッファに入りきらない場合だ。

実際の共有バッファは数千、数万ブロックをキャッシュできるが、ここでは説明のために4ブロックまでデータをキャッシュできるとする。一方、順スキャン対象のテーブルは6ブロックの大きさを持つとする。

ここでセッション1がこのテーブルを最後まで読み込むと、共有バッファ上にはブロック番号3/4/5/6が残ることになる。ブロック番号1と2は、入りきらないので捨てられてしまった。

次にセッション2がこのテーブルを読み込み始める。ブロック1、2は共有バッファにキャッシュされていないので、キャッシュヒット率0となってしまう。ここで1/2ブロックを読み込むと、5/6ブロックが共有バッファから捨てられ、結局キャッシュとして有効に利用できたのは3/4ブロックだけということになる。

そこで登場したのが同期スキャンだ。

同期スキャンでは、上の例で言えば、セッション2は1ブロックではなく、共有バッファにすでにキャッシュされている3 ブロックから読み込みを開始する。そして6ブロックまで読み込んでから、共有バッファにキャッシュされていない1/2ブロックディスクからを読み出すのである。これにより、先ほどは2個のブロックしかキャッシュを利用できていなかったのが、同期スキャンによって4個のブロックをキャッシュから読み込めるようになり、共有バッファのキャッシュ利用効率が格段に高くなっている。