Vacuum 시간 최소화
Amazon Redshift는 백그라운드에서 자동으로 데이터를 정렬하고 VACUUM DELETE를 실행합니다. 이렇게 하면 VACUUM 명령을 실행할 필요성이 줄어듭니다. Vacuum은 시간이 많이 걸릴 수 있는 프로세스입니다. 데이터의 성격에 따라 다르지만, Vacuum 시간을 최소화하려면 다음과 같은 방식을 따르는 것이 좋습니다.
reindex 실행 여부 결정
인터리브 정렬 스타일을 사용하면 종종 쿼리 성능을 크게 높일 수 있지만 정렬 키 열의 값 분산이 변경되면 시간이 지남에 따라 성능이 저하될 수 있습니다.
COPY 또는 CREATE TABLE AS를 사용하여 비어 있는 인터리브 테이블에 처음 로드할 때는 Amazon Redshift가 인터리브 인덱스를 자동으로 구축합니다. INSERT를 사용하여 인터리브 테이블에 처음 로드하는 경우에는 이후 VACUUM REINDEX를 실행하여 인터리브 인덱스를 초기화해야 합니다.
시간이 지나면서 새로운 정렬 키 값이 포함된 행을 추가하여 정렬 키 열의 값 분산이 바뀌면 성능이 떨어질 수 있습니다. 하지만 새로운 행이 기존 정렬 키 값의 범위만 벗어나지 않는다면 인덱스를 다시 빌드할 필요가 없습니다. VACUUM SORT ONLY 또는 VACUUM FULL을 실행하여 정렬 순서를 복원하십시오.
쿼리 엔진은 정렬 순서를 사용하여 쿼리 처리를 위해 스캔해야 하는 데이터 블록을 효율적으로 선택할 수 있습니다. 인터리브 정렬의 경우 Amazon Redshift는 정렬 키 열 값을 분석하여 최적의 정렬 순서를 결정합니다. 행이 추가되어 키 값의 분산이 변경되거나 스큐되면 정렬 전략이 더 이상 최적이 아니게 되며, 정렬의 성능상 이득이 저하됩니다. 정렬 키 분산을 다시 분석하기 위해 VACUUM REINDEX를 실행할 수 있습니다. reindex 작업은 시간이 많이 걸리므로 reindex가 테이블에 이득이 될지 결정하려면 SVV_INTERLEAVED_COLUMNS 뷰를 쿼리하십시오.
예를 들어 다음 쿼리는 인터리브 정렬 키를 사용하는 테이블의 세부 정보를 보여 줍니다.
select tbl as tbl_id, stv_tbl_perm.name as table_name, col, interleaved_skew, last_reindex from svv_interleaved_columns, stv_tbl_perm where svv_interleaved_columns.tbl = stv_tbl_perm.id and interleaved_skew is not null;
tbl_id | table_name | col | interleaved_skew | last_reindex --------+------------+-----+------------------+-------------------- 100048 | customer | 0 | 3.65 | 2015-04-22 22:05:45 100068 | lineorder | 1 | 2.65 | 2015-04-22 22:05:45 100072 | part | 0 | 1.65 | 2015-04-22 22:05:45 100077 | supplier | 1 | 1.00 | 2015-04-22 22:05:45 (4 rows)
interleaved_skew
의 값은 스큐의 양을 나타내는 비율입니다. 값이 1이면 적용된 제한이 없는 것입니다. 스큐가 1.4보다 크면 일반적으로 스큐가 기본 집합에 내재하지 않는 한 VACUUM REINDEX로 성능이 개선됩니다.
last_reindex
의 날짜 값을 사용하면 마지막 reindex 후 얼마나 지났는지 확인할 수 있습니다.
정렬되지 않은 리전 크기 줄이기
이미 데이터가 포함되어 있는 테이블에 대량의 새 데이터를 로드하거나 일상적 유지 관리 작업의 일환으로 테이블을 vacuum하지 않으면 정렬되지 않은 리전이 늘어납니다. vacuum 작업이 오래 실행되는 것을 방지하려면 다음과 같은 습관을 들이십시오.
-
정기적인 일정에 따라 vacuum 작업을 실행합니다.
테이블을 조금씩 증분하여 로드하는 경우(테이블의 전체 행 수의 작은 비율에 해당하는 일일 업데이트 등), 정기적으로 VACUUM을 실행하면 개별 vacuum 작업이 빠르게 진행되는 데 도움이 됩니다.
-
가장 큰 로드를 먼저 실행합니다.
COPY 작업을 여러 번 사용하여 새 테이블을 로드해야 하는 경우, 가장 큰 로드를 먼저 실행합니다. 새 테이블이나 잘린 테이블에 첫 로드를 실행할 때는 정렬된 리전으로 모든 데이터가 직접 로드되므로 vacuum이 필요하지 않습니다.
-
모든 행을 삭제하는 대신 테이블을 자릅니다.
테이블에 행을 삭제해도 vacuum 작업을 수행할 때까지는 행이 차지하던 공간이 회수되지 않습니다. 그러나 테이블을 자르면 테이블이 비워 지고 디스크 공간이 회수되므로 vacuum이 필요하지 않습니다. 또는 테이블을 삭제하고 다시 만드십시오.
-
테스트 테이블을 자르거나 삭제합니다.
테스트 목적으로 소수의 행을 테이블에 로드하는 경우, 로드가 끝난 후 행을 삭제하지 마십시오. 그 대신 테이블을 자르고 후속 프로덕션 로드 작업의 일환으로 이 행들을 다시 로드합니다.
-
전체 복사를 수행합니다.
복합 정렬 키를 사용하는 테이블에 정렬되지 않은 큰 리전이 있는 경우, 전체 복사가 vacuum보다 훨씬 빠릅니다. 전체 복사는 대량 삽입을 사용하여 테이블을 다시 생성하고 다시 채움으로써 테이블을 자동으로 다시 정렬합니다. 테이블에 정렬되지 않은 큰 리전이 있는 경우, 전체 복사가 vacuum보다 훨씬 빠릅니다. 반면 전체 복사 작업 중에는 vacuum 중에는 가능한 동시 업데이트를 할 수 없다는 단점이 있습니다. 자세한 내용은 Amazon Redshift 쿼리 설계 모범 사례 단원을 참조하십시오.
병합된 행의 볼륨 줄이기
vacuum 작업이 새 행을 테이블의 정렬된 리전에 병합해야 하는 경우, 테이블이 커질수록 vacuum에 필요한 시간이 늘어납니다. 병합해야 하는 행의 수를 줄이면 vacuum 성능을 높일 수 있습니다.
vacuum 전에 테이블은 테이블 헤드에 있는 정렬된 리전과 그 뒤에 오는, 행이 추가되거나 업데이트될 때마다 증가하는 정렬되지 않은 리전으로 구성됩니다. COPY 작업에 의해 행 세트가 추가되면 새로운 행 세트는 테이블 끝에 있는 정렬되지 않은 리전에 추가될 때 정렬 키에서 정렬됩니다. 새 행들은 자체 세트 안에서는 정렬되어 있지만 정렬되지 않은 리전 안에서는 그렇지 않습니다.
다음 다이어그램은 2회 연속 COPY 작업 후의 정렬되지 않은 리전을 보여 주며, 여기서 정렬 키는 CUSTID입니다. 이 예에는 간단히 하기 위해 복합 정렬 키가 나와 있지만 정렬되지 않은 리전의 효과가 더 크다는 점만 제외하면 인터리브 정렬 키에도 동일한 원리가 적용됩니다.
vacuum은 2단계로 테이블의 정렬 순서를 복원합니다.
-
정렬되지 않은 리전을 새로 정렬된 리전으로 정렬합니다.
첫 번째 단계는 비교적 리소스를 적게 사용하는데 정렬되지 않은 리전만 다시 작성되기 때문입니다. 새로 정렬된 리전의 정렬 키 값의 범위가 기존 범위보다 높다면 새 행들만 다시 작성하면 되며, vacuum이 완료됩니다. 예를 들어 정렬된 리전에 ID 값 1~500이 포함되어 있고 후속 복사 작업이 500보다 큰 키 값을 추가하는 경우, 정렬되지 않은 리전을 재작성하면 됩니다.
-
새로 정렬된 리전과 이전에 정렬된 리전을 병합합니다.
새로 정렬된 리전의 키가 정렬된 리전의 키와 중첩되는 경우, VACUUM은 행을 병합해야 합니다. vacuum은 새로 정렬된 리전의 시작 부분(가장 낮은 정렬 키)에서 시작해 이전에 정렬된 리전과 새로 정렬된 리전의 병합된 행들을 새 블록 세트에 작성합니다.
새 정렬 키 범위와 기존 정렬 키의 중첩 정도는 이전에 정렬된 리전을 어느 정도까지 다시 작성해야 하는지 결정합니다. 정렬되지 않은 키가 기존 정렬 범위 전체에 흩어져 있는 경우, vacuum은 테이블의 기존 부분을 다시 작성해야 할 수 있습니다.
다음 다이어그램은 CUSTID가 정렬 키인 테이블에 추가되는 행들을 vacuum이 어떻게 정렬하고 병합하는지 보여 줍니다. 각각의 복사 작업이 기존 키와 중첩되는 키 값을 가진 새로운 행 세트를 추가하기 때문에 거의 테이블 전체를 다시 작성해야 합니다. 이 다이어그램에는 단일 정렬 및 병합이 나와 있지만 실제로 큰 vacuum은 일련의 증분적 정렬 및 병합 단계로 구성됩니다.
새로운 행 세트의 정렬 키 범위가 기존 키의 범위와 중첩되는 경우, 병합 단계 비용은 테이블이 커지는 데 따라 테이블 크기에 비례하여 계속 증가하는 반면 정렬 단계의 비용은 정렬되지 않은 리전의 크기에 여전히 비례합니다. 이런 경우, 다음 다이어그램에서 보듯 병합 단계의 비용은 정렬 단계의 비용과의 비교가 무색합니다.
테이블 중에서 다시 병합된 비율을 확인하려면 vacuum 작업이 완료된 후 SVV_VACUUM_SUMMARY를 쿼리합니다. 다음 쿼리는 시간이 흐르면서 CUSTSALES가 계속 커짐에 따른 6회 연속 vacuum의 효과를 보여 줍니다.
select * from svv_vacuum_summary where table_name = 'custsales';
table_name | xid | sort_ | merge_ | elapsed_ | row_ | sortedrow_ | block_ | max_merge_ | | partitions | increments | time | delta | delta | delta | partitions -----------+------+------------+------------+------------+-------+------------+---------+--------------- custsales | 7072 | 3 | 2 | 143918314 | 0 | 88297472 | 1524 | 47 custsales | 7122 | 3 | 3 | 164157882 | 0 | 88297472 | 772 | 47 custsales | 7212 | 3 | 4 | 187433171 | 0 | 88297472 | 767 | 47 custsales | 7289 | 3 | 4 | 255482945 | 0 | 88297472 | 770 | 47 custsales | 7420 | 3 | 5 | 316583833 | 0 | 88297472 | 769 | 47 custsales | 9007 | 3 | 6 | 306685472 | 0 | 88297472 | 772 | 47 (6 rows)
merge_increments 열은 각각의 vacuum 작업을 위해 병합된 데이터 양을 표시합니다. 연속적 vacuum 동안 병합 증분의 수가 테이블 크기 증가에 비례하여 증가하는 경우, 이는 기존의 정렬된 리전과 새로 정렬된 리전이 중첩되기 때문에 각각의 vacuum 작업이 다시 병합하는 이 테이블의 행이 증가하고 있다는 뜻입니다.
정렬 키 순서로 데이터 로드
COPY 명령을 사용하여 데이터를 정렬 키 순서로 로드하면 vacuum 필요성을 줄이거나 심지어 없앨 수도 있습니다.
다음이 모두 참인 경우, COPY는 새 행을 테이블의 정렬된 리전에 자동으로 추가합니다.
-
테이블이 하나의 정렬 열에만 복합 정렬 키를 사용합니다.
-
정렬 열은 NOT NULL입니다.
-
테이블이 100% 정렬되어 있거나 비어 있습니다.
-
모든 새 행은 삭제 대기 상태인 행을 포함하여 기존 행보다 정렬 순서가 더 높습니다. 이 인스턴스에서 Amazon Redshift는 정렬 키의 첫 8바이트를 사용하여 정렬 순서를 결정합니다.
예를 들어 고객 ID와 시간을 사용하여 고객 이벤트를 기록하는 테이블이 있다고 가정해 보십시오. 고객 ID에서 정렬하는 경우, 앞의 예에서 보듯 증분적 로드에 의해 추가된 새 행의 정렬 키 범위가 기존 범위와 중첩되어 vacuum 작업이 리소스를 많이 사용하게 됩니다.
정렬 키를 타임스탬프 열로 설정하면 다음 다이어그램에 나온 것처럼 새 행들이 테이블 끝에서 정렬 순서로 추가되어 vacuum 필요성이 줄어들거나 심지어 없어집니다.
시계열 테이블을 사용하여 저장된 데이터 줄이기
롤링 기간 동안 데이터를 유지하는 경우, 다음 다이어그램에 나온 것처럼 시계열 테이블을 사용하십시오.
데이터 세트를 추가할 때마다 새 테이블을 만든 다음 시계열에서 가장 오래된 테이블을 삭제합니다. 두 가지 장점이 있습니다.
-
DROP TABLE 작업이 대량 DELETE보다 훨씬 효율적이기 때문에 행 삭제에 따른 비용 추가를 피할 수 있습니다.
-
테이블이 타임스탬프를 기준으로 정렬되면 vacuum이 필요 없습니다. 각 테이블에 한 달 동안의 데이터가 포함된 경우, 테이블이 타임스탬프를 기준으로 정렬되어 있지 않더라도 vacuum이 다시 써야 하는 데이터 양은 한 달치에 불과합니다.
데이터가 여러 테이블에 저장되어 있다는 사실을 감추는, 보고 쿼리가 사용할 UNION ALL 뷰를 생성할 수 있습니다. 쿼리가 정렬 키에서 필터를 적용하는 경우, 쿼리 플래너는 사용되지 않는 모든 테이블을 효율적으로 건너뜁니다. 다른 유형의 쿼리에는 UNION ALL이 비효율적일 수 있으므로 테이블을 사용하는 모든 쿼리의 컨텍스트에서 쿼리 성능을 평가해야 합니다.