데이터이야기

DB 노하우, 데이터직무, 다양한 인터뷰를 만나보세요.

생각의 전환이 데이터베이스를 최적화 시킨다. - 6부

데이터 이야기
작성자
dataonair
작성일
2016-03-23 00:00
조회
3744


클러스터 팩터 최적화를 위해 파티션 테이블을 이용해라.

클러스터 팩터 최적화와 파티션 테이블은 매우 밀접한 관계에 있다. 파티션 테이블을 이용하여 어떤 아키텍쳐를 구현하는가에 따라 우리는 좀더 쉽게 클러스터 팩터를 최적화할 수 있을 것이다. 이제부터 파티션 테이블과 클러스터 팩터 최적화를 결합해 보자. 아래와 같은 조건에 의해 클러스터 팩터 최적화를 고려해보자.

n 카드의 거래내역 데이터를 저장하는 테이블

n 카드번호 조건으로 거래내역 조회 발생

이와 같은 조건의 업무라면 기존에는 어떻게 데이터가 저장되어 있었을까 해당 테이블은 거래일자 컬럼에 의해 클러스터 팩터가 최적화되어 있을 것이다. 이는 거래일자에 의해 데이터가 저장되기 때문이다. 하지만 지금 원하는 것은 카드번호 조건으로 데이터를 엑세스하기 때문에 카드번호 컬럼으로 클러스터 팩터를 최적화하는 것이다. 왜 카드번호 컬럼으로 최적화를 수행해야 하는가 거래내역 테이블을 확인해 보자. 거래내역 테이블은 거래일자로 데이터가 저장되기 때문에 동일한 카드번호 값을 가지는 데이터는 동일한 블록에 저장될 가능성이 거의 없다. 이 뜻은 무엇을 의미하는가 해당 카드로 하루에 2번씩 일년간 사용했다고 가정하자. 그렇다면 해당 카드번호 값에 대한 거래내역 데이터는 730건의 거래내역 데이터가 존재하게 될 것이다. 이와 같은 730건의 데이터가 동일한 블록에 저장될 가능성은 거의 없으며 모든 데이터는 730개의 블록에 1건의 데이터씩 저장이 될 것이다. 이와 같은 현상은 왜 발생하는가 해당 카드회사에서는 발생하는 많은 거래 데이터 중 하나의 카드에 의해 사용된 거래내역이 동일 블록에 저장될 확률은 매우 희박하기 때문이다. 따라서, 위와 같다면 카드번호 조건으로 데이터를 조회하는 거래 내역 조회는 하나의 블록에서 하나의 데이터를 추출하게 될 것이다. 따라서, 카드번호 조건으로 조회하는 거래 내역 조회의 성능을 향상시키기 위해서는 카드번호 컬럼으로 클러스터 팩터를 최적화해야 할 것이다.

그렇다면 어떤 방식으로 클러스터 팩터를 최적화할 것인가 우선 아래 항목을 고려해야 할 것이다.

n 전체 데이터에 대한 클러스터 팩터 최적화

n 단위 데이터에 대한 클러스터 팩터 최적화

거래내역 테이블의 전체 데이터를 매번 카드번호 컬럼으로 클러스터 팩터를 최적화한다면 이는 서비스 정지시간도 많이 소요되고 클러스터 팩터 최적화 작업에 많은 시간이 소요될 것이다. 그렇기 때문에 단위 데이터에 대한 클러스터 팩터 최적화가 필요할 것이다. 그렇다면 어떤 단위로 클러스터 팩터를 최적화할 것인가 이는 보통의 경우 월별 또는 일별로 단위를 구분하게 된다. 그렇다면 일별로 클러스터 팩터를 최적화한다면 어떠한가 카드별로 평균 하루에 2건의 거래내역 데이터를 발생시킨다면 하루 데이터에 대해 클러스터 팩터를 최적화하여 1년간의 거래내역 데이터를 엑세스한다면 365 블록을 엑세스하게 된다. 그렇다면 기존에 730개의 블록을 엑세스하는 것에 비하면 블록 엑세스가 감소하기 때문에 성능은 향상되겠지만 클러스터 팩터를 최적화하는 노력에 비해서는 기대효과가 높지는 않을 것이다. 그리고 일별 클러스터 팩터를 최적화하고자 한다면 매일 클러스터 팩터를 최적화하기 위한 작업을 수행해야 하므로 이 또한 쉬운 일은 아닐 것이다. 그렇다면 1개월 단위로 클러스터 팩터를 최적화하는 것은 어떠한가 1개월 단위로 클러스터 팩터를 최적화한다면 기존 730개의 블록을 엑세스하는 거래내역 조회에 비하면 1개월에 하나의 블록씩 12개의 블록만 엑세스하게 되므로 더 좋은 성능을 기대할 수 있을 것이다. 또한, 1개월에 한번 클러스터 팩터를 최적화하게 되므로 클러스터 팩터 최적화를 수행하기에 좀더 수월하게 될 것이다. 물론, 12개의 블록은 테이블 블록에 대한 엑세스만을 의미하며 현재 월은 클러스터 팩터를 최적화할 수 없으므로 이보다는 많은 블록을 엑세스하게 될 것이다.

그렇다면 이제 클러스터 팩터 단위는 결정을 하였다. 그렇다면 두 번째로 고려할 점은 무엇인가 두 번째로 고려할 점은 바로 테이블 아키텍쳐이다. 이와 같이 월별로 클러스터 팩터를 최적화하기 위해서는 월별 파티션 테이블로 구성하는 것이 합리적이다. 물론, 일별 클러스터 팩터를 최적화하기 위해서는 일별 파티션 테이블로 테이블을 구성하는 것이 합리적이다. 위에서는 월별로 클러스터 팩터를 최적화하기로 결정했기 때문에 거래내역 테이블을 월별 파티션 테이블로 생성하면 될 것이다.

n 파티션 테이블 구성

위와 같이 파티션 테이블을 선정했다면 그 다음은 무엇을 고려해야 하는가 세 번째로 어떤 작업 절차에 의해 클러스터 팩터를 최적화할지를 결정해야 한다. 우리가 클러스터 팩터를 최적화하기 위한 단위를 결정하고 그에 맞는 파티션 테이블의 구성을 완료했다면 이제 월마다 수행해야 하는 클러스터 팩터 작업에 대한 절차를 서비스에 영향이 없게 최적화해야 할 것이다. 아래의 절차를 확인해 보자.

n 지난 월 파티션과 동일한 구조의 임시 테이블 생성

n 해당 월 파티션의 데이터를 카드번호 컬럼으로 정렬하여 임시 테이블에 저장

n 임시 테이블에 필요 인덱스 생성

n 임시 테이블을 지난 월 파티션과 파티션 교체

위와 같이 작업을 수행한다면 거래내역 테이블의 서비스는 단 몇 초만의 서비스 정지 현상이 발생하게 되며 거래내역 테이블에 대해 카드번호 컬럼으로 클러스터 팩터를 최적화할 수 있을 것이다. 그렇다면 작업 절차에 대해 자세히 확인해 보자.

지난 월 파티션과 동일한 구조의 임시 테이블을 생성하는 부분은 CTAS(CREATE TABLE AS SELECT)를 이용하면 되며 CTAS에서 테이블의 데이터를 제외한 테이블의 형식만을 복사하면 되므로 몇 초 만에 해당 파티션 테이블과 동일한 구조의 테이블을 생성할 수 있다. 물론, 해당 작업으로 인해 서비스 정지는 발생하지 않게 된다.

그 다음으로 수행하게 되는 해당 월 파티션의 데이터를 카드번호 컬럼으로 정렬하여 임시 테이블에 저장하는 작업은 직접 로딩(DIRECT LOADING) 아키텍쳐를 이용해야 한다. 직접 로딩을 이용해야만 빠른 성능을 보장할 수 있게 된다. 아래와 같은 예제를 확인해 보자.

-------------------------------------------------------------------

SQL> ALTER TABLE 거래내역_임시 NOLOGGING;

SQL> INSERT /*+ APPEND */ INTO 거래내역_임시

SELECT * FROM 거래내역

WHERE 거래일자 LIKE 200805%

ORDER BY 카드번호;

SQL> ALTER TABLE 거래내역_임시 LOGGING;

--------------------------------------------------------------------

위와 같이 작업을 수행한다면 우리는 직접 로딩을 통해 거래내역_임시 테이블에 거래내역 테이블의 2008 5월 데이터를 저장할 수 있게 되며 이 경우 직접 로딩의 아키텍쳐를 이용하게 되므로 빠른 성능을 기대할 수 있다. 물론, 이와 같은 경우에 병렬 직접 로딩(PARALLEL DIRECT LOADING)을 이용할 수 도 있다. 해당 작업에서는 거래내역 테이블의 5월 파티션만을 조회하게 되므로 거래내역 테이블에 대한 서비스에는 영향이 없으며 직접 로딩과 NOLOGGING 기법을 사용하게 되므로 빠른 시간에 데이터를 거래내역_임시 테이블에 저장할 수 있게 된다. 데이터를 카드번호 컬럼으로 정렬하게 되므로 거래내역_임시 테이블에는 카드번호 컬럼으로 정렬되어 데이터가 저장된다. 그러므로 임시 테이블은 카드번호 컬럼으로 클러스터 팩터가 최적화된다. 이 뜻은 하나의 블록에는 동일한 카드번호가 저장된다는 의미가 되며 거래일자 컬럼에 대해서는 클러스터 팩터가 불량해진다. 결국, 해당 테이블에서 카드번호 컬럼으로 조회하는 경우에는 속도가 향상되며 거래일자 컬럼으로 조회하는 경우에는 속도 저하가 발생한다.

데이터를 거래내역_임시 테이블에 저장한 후에는 거래내역_임시 테이블에 인덱스를 생성해야 한다. 그래야만 해당 테이블이 거래내역 테이블로 교체되는 순간 바로 인덱스를 사용할 수 있게 된다. 물론, 거래내역_임시 테이블에 인덱스를 생성하게 되므로 기존 거래내역 테이블의 서비스에는 어떠한 영향도 없게 된다. 임시 테이블을 거래내역 테이블의 하나의 파티션으로 구성하기 위해서는 아래와 같이 파티션 교체 명령을 수행해야 한다.

-------------------------------------------------------------------

SQL> ALTER TABLE 거래내역 EXCHANGE PARTITION P_200805 WITH TABLE

거래내역_임시 INCLUDING INDEXES WITHOUT VALIDATION;

--------------------------------------------------------------------

위와 같이 명령어를 수행하여 카드번호 컬럼의 값으로 클러스터 팩터를 최적화한 2008 5월 데이터별 또는 일별로 우리가 원하는 컬럼으로 클러스터 팩터 최적화를 수행할 수 있게 된다.

시스템을 구축하면서 어떤 테이블에 어떤 컬럼으로 클러스터 팩터 최적화를 적용할 것인지를 판단해야 한다. 또한 이와 같은 클러스터 팩터 최적화를 수행하고자 하는 테이블을 선정했다면 이제는 어떤 방법으로 클러스터 팩터를 최적화할 것이며 추후 운영 시에는 어떻게 새로 저장되는 데이터에 대해 클러스터 팩터 최적화를 수행할 것인지를 항상 고민해야 할 것이다. 이와 같은 항목에 우리가 많은 시간과 많은 생각을 한다면 분명히 정답은 존재하게 된다. 정답을 찾았을 때 우리는 해당 시스템의 최적화를 기대할 수 있을 것이다. 우리가 많은 관심을 가지지 않는 클러스터 팩터에서 성능 최적화를 찾을 수 있다는 것은 매우 중요한 사실이다. 이제부터 우리가 운영하고 있는 시스템 또는 새로 구축하는 시스템에서 클러스터 팩터 최적화에 많은 고려를 해야 할 것이다. 클러스터 팩터 최적화는 대용량 데이터베이스에서 성능을 보장하는 방법 중 하나라는 것을 반드시 명심하길 바란다.