소트 튜닝이 필요한 이유
- 소트 오퍼레이션은 수행과정에서 CPU와 메모리를 많이 사용하고, 데이터량이 많을 때
디스크 I/O까지 일으킨다. 많은 서버 리소스를 사용하는 것도 문제지만 부분범위처리를
불가능하게 해 OLTP 환경에서 애플리케이션 성능을 저하시키는 주요인으로 작용하기도 한다.
소트 수행 과정
- 오라클은 데이터 정렬 필요 시 PGA 메모리에 Sort Area를 할당하는데, 그 안에서 처리를
완료할 수 있는지 여부에 따라 소트를 두 가지 유형으로 나눈다.
메모리 소트 : 전체 데이터의 정렬 작업을 메모리 내에서 완료하는 것을 말하며,
'Internal Sort'라고도 한다.
디스크 소트 : 할당받은 Sort Area 내에서 정렬을 완료하지 못해 디스크 공간까지 사용하는
경우를 말하며, 'External Sort'라고도 한다.
- Sort Area 내에서 데이터 정렬을 마무리하는 것이 최적이지만 (-> optimal 소트),
양이 많을 때 정렬된 중간 결과집합을 Temp 테이블스페이스 Temp 세그먼트에 임시 저장한다.
Sort Area가 찰 때마다 Temp 영역에 저장해 둔 중간 단계의 집합을 'Sort Run'이라고 부른다.
Sort Run 생서을 마쳤으면, 이를 다시 Merge해야 정렬된 최종 결과집합을 얻게 된다.
- 소트의 종류
Optimal 소트 : 소트 오퍼레이션이 메모리 내에서만 이루어짐
Onepass 소트 : 정렬 대상 집합이 디스크에 한 번만 쓰임
Multipass 소트 : 정렬 대상 집합이 디스크에 여러 번 쓰임
소트 오퍼레이션 측정
* 먼저 오라클은 Consistent 모드로 읽고 Current 모드로 갱신한다는 것을 염두해두자
* 대규모의 소트 오퍼레이션이 발생하면 db block gets가 발생한다.
( 이유는 아직 모르겠다. )
- 디스크 I/O 시 버퍼캐시를 경유하므로 일반적으로 디스크 블록 I/O 개수가 메모리 블록 I/O
개수를 초과할 수 없다. 그런데 physical reads 값이 consistent gets와 db block gets를 합한
값보다 훨씬 크다면, 디스스 소트 과정에서 발생한 디스크 I/O까지 physical reads에
포함됐기 때문일 수 있다. 또한 SQL을 최초 수행했을 시 하드 파싱 과정에서 발생한
I/O도 해당 값에 포함됐을 수 있다.
Sort Area
- 데이터 정렬을 위해 사용되는 Sort Area는 소트 오퍼레이션이 진행되는 동안
공간이 부족해질때마다 청크 단위로 조금씩 할당된다. 세션마다 사용할 수 있는 최대 크기를
예전에는 Sort_area_size 파라미터로 설정하였으나, 9i부터는 새로 생긴 workarea_size_policy
파라미터를 auto로 설정하면 오라클이 내부적으로 결정한다.
- sort_area_retained_size는 데이터 정렬을 끝내고 나서 결과집합을 모두 Fetch할 때까지
유지할 Sort Area 크기를 지정한다.
참고로, 0으로 설정하면 Fetch가 완료될 때까지 Sort Area크기를 그대로 유지하겠다는 의미
(정렬작업 후 sort area를 반환하느냐 또는 해당 SQL의 fetch 후 sort area를 반환하느냐의 차이)
● PGA
- PGA는 다른 프로세스와 공유되지 않는 독립적인 메모리 공간으로서,
래치 매커니즘이 필요 없어 똑같은 개수의 블록을 읽더라도
SGA 버퍼 캐시에서 읽는 것보다 훨씬 빠르다.
● UGA
- 하나의 프로레스는 하나의 PGA를 갖는다.
- 하나의 세션은 하나의 UGA를 갖는다.
- PGA에는 세션과 독립적인 프로세스만의 정보를 관리한다.
- UGA에는 프로세스와 독립적인 세션만의 정보를 관리한다.
- 거의 대부분 전용 서버 방식을 사용하므로 세션과 프로세스는 1:1 관계고, 따라서
UGA도 PGA 내에 할당된다고 이해하면 쉽다.
- 다만 공유 서버 방식으로 연결할 때는 SGA에 할당된다. 후자 방식에는 구체적으로,
Large Pool이 설정됐을 때는 Large Pool에, 그렇지 않을 때는 Shared Pool에 할당된다.
● CGA
- PGA에 할당되는 메모리 공간으로는 CGA도 있다. 오라클은 하나의 데이터베이스 Call을
넘어서 다음 Call까지 계속 참조되어야 하는 정보는 UGA에 담고,
Call이 진행되는 동안에만 필요한 데이터는 CGA에 담는다.
- CGA에 할당된 공간은 하나의 Call이 끝나자마자 해제돼 PGA로 반환된다.
● CGA : Call이 진행되는 동안만 필요한 정보 저장
● UGA : Call을 넘어서 다음 Call까지 계속 참조되는 정보 저장
Sort Area 할당 위치
1. DML 문장 수행 시 발생하는 소트는 CGA에서 수행
2. SELECT 문장 수행 시
(1) 쿼리 중간 단계의 소트
CGA에서 수행, sort_area_retained_size 제약이 있다면 다음 단계로 넘어가기 전에
이 값을 초과하는 CGA 영역을 반환
(2) 결과 집합을 출력하기 직전 단계에서 수행하느 소트
① sort_area_retained_size 제약이 있다면, CGA에서 소트 수행
이 제약만큼의 UGA를 할당해 정렬된 결과를 담았다가 이후 Fetch Call에서
Array 단위로 전송
① sort_area_retained_size 제약이 없다면, 곧바로 UGA에서 소트 수행
- CGA에 할당된 Sort Area는 하나의 Call이 끝나자마자 PGA에 반환된다. UGA에 할당된
Sort Area는 마지막 로우가 Fetch 될 때 비로소 UGA Heap에 반환되고, 거의 대부분
그 부모 Heap에도 즉각 반한된다.
소트 튜닝 요약
- 소트 오퍼레이션은 메모리 집약적일뿐만 아니라 CPU 집약적이기도 하며,
데이터량이 많을 때는 디스크 I/O까지 발생시키므로 쿼리 성능을 좌우하는 가장 중요한 요소다.
특히, 부분범위처리를 할 수 없게 만들어 OLTP 환경에서 성능을 떨어뜨리는 주요인으로
작용한다. 따라서 될 수 있으면 소트가 발생하지 않도록 SQL을 작성해야 하고,
소트가 불가피하다면 메모리 내에서 수행을 완료할 수 있도록 해야 한다.
- 소트 튜닝 방안의 요약
● 데이터 모델 측면에서의 검토
● 소트가 발생하지 않도록 SQL 작성
● 인덱스를 이용한 소트 연산 대체
● Sort Area를 적게 사용하도록 SQL 작성
● Sort Area 크기 조정