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