특정한 값을 기준으로 데이터를 순서대로 배치하는 작업을 정렬이라고 한다. 프로그래밍을 통해 퀵정렬, 병합 정렬, 버블정렬 등이 있다고 배워왔다. 당연하게도 이러한 정렬 작업은 주기억장치에서 실행된다. 하지만 데이터의 크기가 너무 커, 주기억장치에서 정렬을 진행할 수 없다면 어떻게 될까?
이와 같이 대규모 데이터를 주기억장치 뿐만이 아니라, 보조기억장치까지 이용해 정렬하는 방식을 외부 정렬이라고 한다.
이는 정렬 단계와 병합 단계로 나뉜다. 정렬 단계에서는 런이라는 단위로 데이터들을 파일로 분리한 후 정렬한다. 병합 단계에서는 정렬된 런들을 반복적으로 병합하여 하나의 런인 최종 결과물을 만든다.
병합 단계에는 m-원 합병, 균형 합병, 다단계 합병등의 방법이 있다.
m-원 합병을 구현하려고 한다.
m-원 합병은 런들을 m개씩 병합하는 작업을 반복하여 결과물을 만들어 내는 방식이다.
위의 이미지는 2-원 합병을 통해 하나의 결과물을 만들어내는 과정을 나타낸 것이다.
BlockReader
: 레코드들을 블럭 단위로 읽어오도록 하는 객체이다.BufferManager
: 레코드들을 정렬하여 파일로 저장하는 객체이다.BlockWriter
: 레코드들을 고정길이-블럭단위로 파일에 출력하는 객체이다.lineitem.tbl
을 BlockReader
로 읽는다.BufferManager
에 저장한 후, 설정한 버퍼 크기가 되면 정렬한 후 런 파일로 저장한다.parsePartKey()
을 통해 PARTKEY
를 기준으로 오름차순 정렬하였다.lineitem.tbl
을 다 읽을 때까지 실행한다.run1
)을 output.tbl
에 저장한다.(m-원 병합을 진행할 인덱스들[어느 런부터 어느런까지 병합하는지, 현재 병합 깊이가 어떻게 되는지]를 조정하는 것이 어려웠다.)
O(NlogN)
일 것이다.O(B+M)
이다.N % M == 0
이 되는 M과 B가 최적해일 것이다.버퍼 크기 | 최대 메모리 크기 | 실행 시간 (ms) |
---|---|---|
1 | 6188KB | 639.806 |
750 | 8252KB | 108.542 |
1250 | 8264KB | 106.633 |
1375 | 8420KB | 104.22 |
1382 | 8500KB | 110.425 |
1390 | 8512KB | 110.772 |
1406 | 8544KB | 104.824 |
1437 | 8568KB | 103.345 |
1500 | 8664KB | 82.733 |
3000 | 9308KB | 87.237 |
6000 | 10324KB | 98.386 |
7500 | 10440KB | 85.734 |