CLUSTER — 인덱스에 따라 테이블 클러스터링하기

CLUSTER — 인덱스에 따라 테이블 클러스터링하기

CLUSTER 명령은 인덱스의 정렬 순서에 따라 테이블의 물리적 행 순서를 재배열해서, 관련 데이터를 한곳에 모아 검색 성능을 높이는 PostgreSQL 명령이에요. 대량 선택(범위 스캔)에서 디스크 접근을 줄이는 데 효과적이에요.

출처: PostgreSQL 문서

본문

Synopsis

CLUSTER [ ( option [, ...] ) ] [ table_name [ USING index_name ] ]

where option can be one of:

    VERBOSE [ boolean ]

Description

CLUSTER는 *index_name*으로 지정한 인덱스를 기준으로 *table_name*으로 지정한 테이블을 클러스터링하라고 PostgreSQL에 지시해요. 해당 인덱스는 이미 *table_name*에 정의되어 있어야 해요.

테이블이 클러스터링되면 인덱스 정보에 따라 물리적으로 재정렬돼요. 클러스터링은 일회성 작업이에요. 테이블이 나중에 갱신되면 그 변경 사항은 클러스터링되지 않아요. 즉 새 행이나 갱신된 행을 인덱스 순서대로 저장하려는 시도 자체가 없다는 뜻이에요. (원한다면 명령을 다시 실행해 주기적으로 재클러스터링할 수 있어요. 또한 테이블의 fillfactor 저장소 매개변수를 100% 미만으로 설정하면 갱신된 행을 같은 페이지에 유지할 수 있어 갱신 중에도 클러스터 순서를 보존하는 데 도움이 돼요.)

테이블이 클러스터링되면 PostgreSQL은 어떤 인덱스로 클러스터링했는지 기억해요. CLUSTER *table_name* 형태는 이전과 동일한 인덱스를 사용해 테이블을 재클러스터링해요. ALTER TABLECLUSTER 또는 SET WITHOUT CLUSTER 형태를 사용해 향후 클러스터 작업에 사용할 인덱스를 설정하거나, 이전 설정을 지울 수도 있어요.

table_name 없이 CLUSTER를 실행하면, 호출한 사용자가 권한을 가진 현재 데이터베이스의 모든 이전에 클러스터링된 테이블을 재클러스터링해요. 이 형태의 CLUSTER는 트랜잭션 블록 안에서는 실행할 수 없어요.

테이블이 클러스터링되는 동안 그 테이블에 ACCESS EXCLUSIVE 잠금이 획득돼요. 이로 인해 CLUSTER가 끝날 때까지 다른 모든 데이터베이스 작업(읽기와 쓰기 모두)이 그 테이블에서 실행되지 못해요.

Parameters

table_name

(스키마 한정일 수 있는) 테이블의 이름이에요.

index_name

인덱스의 이름이에요.

VERBOSE

각 테이블이 클러스터링될 때마다 INFO 수준으로 진행 보고를 출력해요.

boolean

선택한 옵션을 켤지 끌지 지정해요. 옵션을 활성화하려면 TRUE, ON, 1을, 비활성화하려면 FALSE, OFF, 0을 쓸 수 있어요. boolean 값은 생략할 수도 있는데, 생략하면 TRUE로 간주돼요.

Notes

테이블을 클러스터링하려면 그 테이블에 MAINTAIN 권한이 있어야 해요.

테이블 내에서 단일 행을 무작위로 접근하는 경우에는 테이블 안 데이터의 실제 순서가 중요하지 않아요. 하지만 어떤 데이터를 다른 데이터보다 더 자주 접근하고, 그 데이터들을 함께 묶어주는 인덱스가 있다면 CLUSTER를 사용하는 것이 유리해요. 테이블에서 인덱스된 값의 범위를 요청하거나, 일치하는 여러 행을 가진 단일 인덱스 값을 요청하는 경우 CLUSTER가 도움이 돼요. 인덱스가 일치하는 첫 행이 있는 테이블 페이지를 식별하면, 나머지 일치 행들은 대개 이미 같은 테이블 페이지에 있기 때문에 디스크 접근을 줄이고 쿼리를 빠르게 만들 수 있어요.

CLUSTER는 지정된 인덱스에 대한 인덱스 스캔을 사용하거나, (인덱스가 b-tree라면) 순차 스캔 후 정렬로 테이블을 재정렬할 수 있어요. 플래너 비용 매개변수와 사용 가능한 통계 정보를 바탕으로 더 빠른 방법을 선택하려고 시도해요.

CLUSTER가 실행되는 동안 search_path는 일시적으로 pg_catalog, pg_temp로 변경돼요.

인덱스 스캔을 사용하면, 테이블 데이터를 인덱스 순서로 담은 테이블의 임시 사본이 생성돼요. 테이블의 각 인덱스의 임시 사본도 생성돼요. 따라서 테이블 크기와 인덱스 크기의 합 이상의 여유 디스크 공간이 필요해요.

순차 스캔과 정렬을 사용하면 임시 정렬 파일도 생성되므로, 최대 임시 공간 요구량이 테이블 크기의 두 배에 인덱스 크기를 더한 만큼이 돼요. 이 방법은 인덱스 스캔 방법보다 보통 더 빠르지만, 디스크 공간 요구량이 참을 수 없을 정도라면 enable_sort를 일시적으로 off로 설정해 이 선택을 비활성화할 수 있어요.

클러스터링 전에 maintenance_work_mem을 합리적으로 큰 값으로 설정하는 것이 좋아요. (단, CLUSTER 작업에 전용할 수 있는 RAM 양보다 많지 않게요.)

플래너는 테이블 순서에 대한 통계를 기록하므로, 새로 클러스터링된 테이블에 ANALYZE를 실행하는 것이 좋아요. 그렇지 않으면 플래너가 잘못된 쿼리 계획을 선택할 수 있어요.

CLUSTER는 어떤 인덱스가 클러스터링됐는지 기억하기 때문에, 처음에는 원하는 테이블을 수동으로 한 번 클러스터링한 다음, 매개변수 없이 CLUSTER를 실행하는 주기적 유지보수 스크립트를 설정하면 원하는 테이블을 주기적으로 재클러스터링할 수 있어요.

각 백엔드가 실행 중인 CLUSTER의 진행 상황을 pg_stat_progress_cluster 뷰에서 보고해요. 자세한 내용은 27.4.2 절을 참고해요.

파티션 테이블을 클러스터링하면 지정된 파티션 인덱스의 파티션을 사용해 각 파티션을 클러스터링해요. 파티션 테이블을 클러스터링할 때는 인덱스를 생략할 수 없어요. 파티션 테이블에 대한 CLUSTER는 트랜잭션 블록 안에서 실행할 수 없어요.

Examples

employees_ind 인덱스를 기준으로 employees 테이블을 클러스터링하기:

CLUSTER employees USING employees_ind;

이전에 사용했던 것과 같은 인덱스로 employees 테이블을 클러스터링하기:

CLUSTER employees;

데이터베이스에서 이전에 클러스터링된 모든 테이블을 클러스터링하기:

CLUSTER;

Compatibility

SQL 표준에는 CLUSTER 문이 없어요.

PostgreSQL 17 이전에 사용되던 문법이며 여전히 지원되는 형태:

CLUSTER [ VERBOSE ] [ table_name [ USING index_name ] ]

PostgreSQL 8.3 이전에 사용되던 문법이며 여전히 지원되는 형태:

CLUSTER index_name ON table_name

더 알아보기 (Learn more)