ablog

不器用で落着きのない技術者のメモ

Amazon Redshift と PostgreSQL の VACUUM FULL の動作の違い

Amazon Redshift と PostgreSQL の VACUUM FULL の動作は似ているが少し違う。どちらも空き領域を再利用するが、Redshift は「行を再ソート」する点が違う。これはそもそも、Redshift と PostgreSQL のデータ構造が異なるためで、PostgreSQL は行指向データベースのいわゆる再編成なのに対して、Redshift は行指向でソート済データを格納していて*1、ソートされてないとスキャン効率が悪化*2するためと思われる。

Amazon Redshift の VACUUM コマンドの構文と動作は、PostgreSQL の VACUUM 操作とは大幅に異なります。たとえば、Amazon Redshift でのデフォルトのバキューム操作は VACUUM FULL です。これは、ディスク領域を再利用し、すべての行を再ソートします。 これに対して、PostgreSQL のデフォルトの VACUUM 操作は、単純に領域を再利用し、再び使用できるようにするだけです。


(中略)


FULL
指定されたテーブル (または現在のデータベースのすべてのテーブル) をソートし、直前の UPDATE 操作および DELETE 操作で削除対象のマークが付けられた行によって占有されているディスク領域を再利用します。完全バキュームは、インターリーブテーブルのインデックスを再作成しません。 インターリーブテーブルのインデックスを再作成するには、VACUUM REINDEX オプションを使用します。
デフォルトで、VACUUM FULL は、少なくとも 95 パーセントがソート済みであるテーブルのソートフェーズをすべてスキップします。 VACUUM がソートフェーズをスキップできれば、DELETE ONLY を実行し、削除フェーズで残りの行の少なくとも 95 パーセントが削除対象としてマークされていない領域を再利用します。
ソートしきい値に達しておらず (たとえば 90 パーセントの行がソートされていて) VACUUM が完全ソートを実行する場合は、完全な削除オペレーションも実行され、削除された行のスペースが 100 パーセント回復されます。
一つのテーブルに対してのみデフォルトの VACUUM しきい値を変更できます。 1 つのテーブルに対するデフォルトの VACUUM しきい値を変更するには、テーブル名および TO threshold PERCENT パラメータを含めます。

VACUUM - Amazon Redshift

テーブルの作成時に、その 1 つ以上の列をソートキーとして定義することができます。データが空のテーブルに最初にロードされると、行がディスク上にソート順に格納されます。ソートキー列に関する情報がクエリプランナーに渡され、プランナはこの情報を使用して、データのソート方法を利用するプランを構築します。

ソートは、範囲が制限された述語を効率的に処理することができます。Amazon Redshift は、列データを 1 MB のディスクブロックに格納します。各ブロックの最小値と最大値がメタデータの一部として格納されます。範囲が制限された述語をクエリが使用する場合、クエリプロセッサは最小値と最大値を使用して、テーブルスキャン中に多数のブロックをすばやくスキップすることができます。

ソートキーの選択 - Amazon Redshift

(FULLの無い)通常のVACUUMは単に領域を回収し、そこを再利用可能な状態に変更します。 排他的ロックが取得されていないため、この形のコマンドは、テーブルへの通常の読み書き操作と並行して実行することができます。 VACUUM FULLは、ディスクブロック数を最小にするためのブロックを跨るタプルの移動など、テーブルを縮小させるためにもっと高度な処理を行ないます。 この場合、かなり低速になり、また、処理中のテーブルに対する排他的ロックが必要になります。

http://www.postgresql.jp/document/pg802doc/html/sql-vacuum.html

*1:ソートキーを指定している場合

*2:ゾーンマップでブロック読込をスキップできるケースで