CLUSTERは、indexnameで指定されたインデックスに基づき、tablenameで指定されたテーブルをクラスタ化するように、PostgreSQLに指示します。 このインデックスは前もってtablenameで定義されていなければなりません。
テーブルがクラスタ化されると、それぞれのテーブルはインデックス情報に基づいて物理的に並べ直されます。 クラスタ化は、1回限りの操作です。 クラスタ化後にテーブルが更新されても、その変更はクラスタ化されません。 つまり、新規に追加された行や更新された行は、インデックス順には保管されません。 インデックス順に保管したい場合は、コマンドを再度入力し、定期的に再クラスタ化を行います。
テーブルがクラスタ化されると、PostgreSQLはクラスタ化に使用されたインデックスを記録します。 CLUSTER tablenameという構文によって、以前にクラスタ化された時と同じインデックスを使用してテーブルを再クラスタ化します。
パラメータを指定しないでCLUSTERを実行した場合、呼び出したユーザが所有するデータベース内の全てのテーブルを(スーパーユーザの場合は、全てのテーブルを)クラスタ化します (これまでにクラスタ化されていないテーブルは含まれません)。 このパラメータを指定しないCLUSTERを、トランザクションブロック内で実行することはできません。
クラスタ化を行っているテーブルは、ACCESS EXCLUSIVEロックを獲得しています。 これにより、CLUSTERが終わるまで、そのテーブルに対するデータベース操作(読み書き両方)を防ぐことができます。
CLUSTERは、タプルの可視性に関する情報をすべて失います。 このため、CLUSTERコマンドが終了する前に作られたスナップショットから見ると、このテーブルは空に見えます。 クラスタ化対象のテーブルにアクセスするトランザクションをCLUSTERと同時に実行するようなアプリケーションでは、CLUSTERは適さないことになります。 そのトランザクションの先頭で1つだけスナップショットが作成されますので、シリアライザブルなトランザクションではほぼ可視です。 しかし、リードコミッテッドトランザクションでは影響を受けます。
テーブル内の1つの行にランダムにアクセスする場合、テーブル内のデータの順序は重要でありません。 しかし、テーブル内の特定のデータにアクセスが集中している場合、それらのデータをグループ化しているインデックスが存在する時は、CLUSTERによる利益を享受できます。 テーブルからインデックスの値の範囲や、一致する複数の行を保有する1つのインデックスの値などが知りたい場合、CLUSTERが役に立ちます。 一度インデックスが一致する行に対するテーブルページを認識すると、一致する他の全ての行も同じテーブルページに存在する可能性が高いので、ディスクアクセスを減らして問い合わせ処理の速度を向上することができるからです。
クラスタ処理の間、インデックス順にテーブルデータを並べた、テーブルの一時コピーが作成されます。 同様に、テーブルの各インデックスの一時コピーも作成されます。 したがって、ディスクには、少なくともテーブルとインデックスの合計サイズと同じ容量の空き領域が必要です。
CLUSTERはクラスタ化に関する情報を記録しているので、一度手作業でテーブルをクラスタ化すれば、周期的に再クラスタ化を実行するよう、VACUUM同様にスケジュールを組むことができます。
プランナはテーブルの順序付けに関する統計情報を記録しているため、新しくクラスタ化されたテーブルでは、ANALYZEを実行することが推奨されます。 そうしないと、プランナが問い合わせ計画を適切に選択できない可能性があります。
データをクラスタ化する方法はもう1つあります。 CLUSTERコマンドは、指定したインデックスを使用してテーブルをスキャンすることで元のテーブルを並び替えます。 この方法では、行はインデックスの順序にテーブルから取り出されますが、テーブルが順番に並んでいない場合、それぞれの項目がばらばらの順序でページ上に存在するため、移動する行ごとに1つのディスクページが取得されることになります。 したがって、大規模なテーブルでは低速になることがあります (PostgreSQLにはキャッシュがありますが、大規模なテーブルの大多数はキャッシュに収めきれません)。 次に、テーブルをクラスタ化するもう1つの方法を示します。
CREATE TABLE newtable AS SELECT * FROM table ORDER BY columnlist;
このSQL文では、PostgreSQLのソート用のコードを使用し、必要な並び替えを作成しています。 この方法は、通常、順序付けられていないデータに対するインデックススキャンよりも処理時間がずっと短くなります。 その後、古いテーブルを削除し、ALTER TABLE...RENAMEでnewtableを以前の名前に書き換えてから、テーブルのインデックスを再生成してください。 しかし、この方法では、テーブルのOID、制約、外部キー関係、権限、およびその他の付属情報が保持されないという大きな欠点があります。 これらの付属情報は、手動で再作成する必要があります。 他にもこの方法には、対象のテーブル自体と同サイズの、一時的なソート用のファイルが必要であるという欠点もあります。 このため、最大のディスク使用量はテーブルサイズの倍ではなく約3倍になります。