Top-N 처리 원리: ROWNUM·FETCH FIRST·STOPKEY
정렬 기준의 앞쪽 N건을 구할 때 ROWNUM 위치와 FETCH FIRST 문법, COUNT·SORT ORDER BY STOPKEY의 실제 읽기 범위를 이해합니다.
핵심 요약
Top-N 조회는 단순히 N건을 반환하는 조회가 아닙니다.
Top-N
= 전체 후보에 업무 정렬 기준을 적용
+ 정렬 기준의 앞쪽 N건을 선택
성능 판단의 핵심입니다.
최종 결과 Row = N건
하지만 실제 작업량은
- 후보를 몇 행 읽었는가?
- 정렬 Key를 몇 행 계산했는가?
- Sort Workarea·TEMP를 얼마나 사용했는가?
- Index·Table Block을 얼마나 읽었는가?
- N건을 찾은 뒤 하위 처리를 실제로 멈췄는가?
로 결정
대표 실행 형태입니다.
입력이 이미 필요한 순서
→ 앞에서 N건 확보
→ 하위 Row Source 요청 중단 가능
→ COUNT STOPKEY·WINDOW NOSORT STOPKEY 등
입력이 필요한 순서가 아님
→ 후보를 읽으면서 상위 N개 유지
→ SORT ORDER BY STOPKEY
→ 입력 전체를 읽을 수도 있음
전체 정렬 후 외부에서 제한
→ 불필요한 Full Sort가 발생할 수 있음
이 이론의 범위
이 이론은 SQLP의
SQL 고급활용 및 튜닝 → 소트 튜닝 → Top-N·STOPKEY범위에서 ROWNUM, Row Limiting Clause, 결정적 ORDER BY, Index Order와 실행계획 검증을 다룹니다.
학습 목표
이 이론을 학습한 뒤에는 다음을 설명할 수 있어야 합니다.
- Top-N 조회와 임의 N건 제한을 구분한다.
- ROWNUM이 Row가 선택되는 과정에서 부여되는 Pseudocolumn임을 설명한다.
- 같은 Query Block의 ROWNUM과 ORDER BY 순서가 결과를 바꾸는 이유를 설명한다.
- ROWNUM Inline View Top-N 구조를 작성한다.
OFFSET,FETCH FIRST,PERCENT,ONLY,WITH TIES의 의미를 설명한다.- 결정적 ORDER BY와 Tie-Breaker의 필요성을 설명한다.
COUNT STOPKEY와SORT ORDER BY STOPKEY의 처리 차이를 설명한다.- STOPKEY 출력 Row와 하위 Access A-Rows를 구분한다.
- Index Range·Full Scan과 Index Fast Full Scan의 순서 제공 차이를 설명한다.
- 추가 Table Filter가 Index 조기 종료를 지연시킬 수 있음을 설명한다.
- Join 전후 Top-N의 대상 Grain을 구분한다.
- ALLSTATS LAST에서 A-Rows·Buffers·Starts로 실제 효율을 검증한다.
1. Top-N과 단순 Row 제한
요구사항입니다.
전체 주문 중 금액이 가장 큰 주문 10건을 반환한다.
두 단계가 필요합니다.
1. 전체 후보에서 주문금액 기준 순서를 결정
2. 그 순서의 앞쪽 10건 선택
다음 SQL은 전체 상위 10건을 보장하지 않습니다.
SELECT order_id,
order_amount
FROM orders
WHERE ROWNUM <= 10
ORDER BY order_amount DESC;
개념적 의미입니다.
Access Path에서 먼저 발견된 10건 선택
→ 선택된 10건만 금액순 정렬
따라서 구분합니다.
임의 10건을 정렬
≠ 전체 후보의 상위 10건
2. ROWNUM의 적용 시점
ROWNUM은 Oracle이 Table 또는 Join Row Source에서 Row를 선택해 반환하는 순서를 나타내는 Pseudocolumn입니다.
첫 번째 선택 Row → ROWNUM 1
두 번째 선택 Row → ROWNUM 2
...
같은 Query Block에서 다음이 함께 있으면:
WHERE ROWNUM <= 10
ORDER BY ...
ROWNUM으로 Row를 제한한 뒤 ORDER BY가 선택된 Row를 재정렬할 수 있습니다. Access Path가 바뀌면 선택되는 Row도 달라질 수 있습니다.
2.1 올바른 ROWNUM Top-N
순서를 안쪽 Query Block에서 먼저 정의합니다.
SELECT order_id,
order_amount
FROM (
SELECT order_id,
order_amount
FROM orders
ORDER BY order_amount DESC,
order_id DESC
)
WHERE ROWNUM <= 10;
처리 의미입니다.
안쪽 Query Block
→ 전체 후보의 결정적 순서 정의
바깥 Query Block
→ 정렬 결과의 앞쪽 10건 제한
2.2 ROWNUM > 1 조건
다음 조건은 Row를 반환하지 않습니다.
WHERE ROWNUM > 1
첫 후보 Row가 ROWNUM 1을 받아 조건을 실패하면, 다음 후보도 다시 첫 반환 후보가 되어 ROWNUM 1을 받으므로 계속 실패합니다.
Pagination은 ROWNUM 범위를 같은 단계에서 단순하게 작성하지 않고, 중첩 Query Block이나 OFFSET ... FETCH를 사용합니다.
2.3 ROWNUM과 View Optimization
ROWNUM을 Query에 사용하면 View Optimization·Transformation에 영향을 줄 수 있습니다. SQL Text의 Inline View 경계와 실제 실행계획의 Query Block·Operation을 함께 확인합니다.
3. Row Limiting Clause
Oracle은 SELECT의 row_limiting_clause로 반환 Row를 제한할 수 있습니다.
3.1 FETCH FIRST
SELECT order_id,
order_amount
FROM orders
ORDER BY order_amount DESC,
order_id DESC
FETCH FIRST 10 ROWS ONLY;
의미입니다.
ORDER BY로 순서를 정의
→ 앞쪽 10행 반환
FIRST와 NEXT, ROW와 ROWS는 문법적으로 의미 차이가 없습니다.
3.2 OFFSET
ORDER BY order_amount DESC,
order_id DESC
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;
앞쪽 20행을 건너뛰고 다음 10행을 반환합니다.
주의합니다.
- 큰 OFFSET은 앞쪽 Row를 처리하고 버리는 비용이 커질 수 있음
- Pagination 중 Data가 변경되면 Page 간 누락·중복이 생길 수 있음
- 안정적 Pagination에는 결정적 ORDER BY가 필요
- 대규모 Pagination은 마지막 Key를 조건에 사용하는 Keyset Pagination도 비교
3.3 PERCENT
FETCH FIRST 10 PERCENT ROWS ONLY;
선택된 전체 결과의 앞쪽 10%를 반환합니다. 정확한 Row 수가 필요한 업무에는 고정 Row Count와 의미가 다릅니다.
3.4 ONLY
FETCH FIRST 10 ROWS ONLY
사용 가능한 Row가 충분하다면 정확히 10행을 반환합니다.
3.5 WITH TIES
ORDER BY score DESC
FETCH FIRST 3 ROWS WITH TIES;
세 번째 Row와 모든 ORDER BY 표현식의 값이 같은 추가 Row를 함께 반환합니다.
정렬 점수: 100, 95, 90, 90, 90, 80
FETCH FIRST 3 ROWS WITH TIES
→ 100, 95, 90, 90, 90
→ 5행 반환
WITH TIES는 ORDER BY가 필요합니다.
4. 결정적 ORDER BY
다음 SQL은 점수가 같은 Row 사이의 순서를 완전히 정의하지 않습니다.
SELECT student_id,
score
FROM exam_result
ORDER BY score DESC
FETCH FIRST 10 ROWS ONLY;
경계에 동일 점수 Row가 여러 건 있으면 어떤 Row가 10건에 포함되는지 비결정적일 수 있습니다.
결정적 정렬입니다.
ORDER BY score DESC,
student_id ASC
FETCH FIRST 10 ROWS ONLY;
student_id가 Unique하면 모든 Row의 전체 순서가 결정됩니다.
4.1 ONLY와 Tie-Breaker
Tie-Breaker는 ONLY의 결과를 안정화합니다.
동점 중 어떤 Row가 포함되는가?
→ Unique Tie-Breaker가 결정
4.2 WITH TIES와 Tie-Breaker
ORDER BY score DESC
FETCH FIRST 3 ROWS WITH TIES;
점수가 같은 모든 경계 Row를 포함합니다.
ORDER BY score DESC,
student_id ASC
FETCH FIRST 3 ROWS WITH TIES;
Unique student_id까지 모든 ORDER BY 값이 같은 서로 다른 Row는 일반적으로 없으므로 결과는 정확히 3행 방향이 됩니다.
즉, WITH TIES의 Tie 기준은 첫 Sort Key 하나가 아니라 ORDER BY 표현식 전체입니다.
5. COUNT STOPKEY
입력이 이미 원하는 순서로 들어오면 필요한 Row를 얻은 후 하위 Row Source 요청을 멈출 수 있습니다.
COUNT STOPKEY
TABLE ACCESS BY INDEX ROWID ORDERS
INDEX RANGE SCAN DESCENDING ORDERS_AMT_IX
개념적 흐름입니다.
Index에서 가장 큰 Key부터 순서대로 읽음
→ Table Row 조회
→ 조건을 만족한 결과 N건 확보
→ 하위 Row 요청 중단
장점입니다.
- 일반 전체 Sort 제거 가능
- 적은 Index Leaf·Table Block만 읽고 중단 가능
- First Row·첫 Page 응답 개선 가능
하지만 Operation 이름만으로 N개의 Index Entry만 읽었다고 단정하지 않습니다.
다음이 있으면 더 많은 후보를 확인할 수 있습니다.
- Index에 없는 Table Filter
- Join 후 Filter
- Key당 중복 Row
- 조건에 맞지 않는 후보 Row
- OFFSET
- WITH TIES의 경계 동점
- Table by ROWID 비용
6. SORT ORDER BY STOPKEY
입력이 필요한 순서가 아니면 Oracle은 후보를 읽으며 상위 N개를 유지하는 Top-N Sort를 사용할 수 있습니다.
SORT ORDER BY STOPKEY
TABLE ACCESS FULL ORDERS
6.1 일반 Full Sort와 차이
일반 Full Sort:
모든 후보를 Sort Workarea·TEMP Run에 정렬
→ 전체 정렬 결과 생성
Top-N Sort:
후보를 읽으면서 현재 상위 N개 중심으로 유지
→ 전체 Row를 모두 Memory에 보관하지 않을 수 있음
따라서 Workarea Memory를 줄일 가능성이 있습니다.
6.2 입력 전체를 읽을 수 있는 이유
정렬되지 않은 후보에서 상위 N개를 확정하려면 마지막 Row까지 더 큰 값이 있는지 확인해야 할 수 있습니다.
SORT ORDER BY STOPKEY A-Rows = 10
TABLE ACCESS FULL A-Rows = 50,000,000
해석입니다.
출력은 10행
하지만 상위값 확정을 위해
하위 후보 5천만 행을 읽음
Top-N 최적화 여부는 출력 Row가 아니라 하위 Access의 A-Rows·Buffers·Reads로 판단합니다.
7. Index Order를 이용한 Top-N
조회입니다.
SELECT order_id,
customer_id,
order_date
FROM orders
WHERE customer_id = :customer_id
ORDER BY order_date DESC,
order_id DESC
FETCH FIRST 20 ROWS ONLY;
후보 Index입니다.
CREATE INDEX orders_cust_date_ix
ON orders(
customer_id,
order_date DESC,
order_id DESC
);
정렬 활용 조건입니다.
customer_id
→ Equality로 한 고객의 Index 범위 고정
order_date DESC, order_id DESC
→ 해당 범위 안에서 요청한 순서 제공
FETCH FIRST 20
→ 앞쪽 Match 20건 확보 후 중단 가능
7.1 순서를 제공할 수 있는 Scan
Plan 조건에 따라 다음 Scan은 Index Key 순서로 RowID를 제공할 수 있습니다.
INDEX RANGE SCANINDEX RANGE SCAN DESCENDINGINDEX FULL SCANINDEX FULL SCAN DESCENDING
7.2 INDEX FAST FULL SCAN
INDEX FAST FULL SCAN은 Multiblock I/O로 Index Block을 Disk에 존재하는 순서대로 읽습니다.
INDEX FULL SCAN
→ Index Key 순서
→ Sort 생략 가능성
INDEX FAST FULL SCAN
→ 정렬되지 않은 Block 순서
→ Sort 생략용 순서 제공 불가
7.3 선두 Column과 전체 순서
Index가 다음과 같아도:
(customer_id, order_date DESC, order_id DESC)
여러 customer_id를 동시에 조회하면 각 고객 범위 안에서만 날짜순일 뿐 전체 결과가 order_date DESC로 합쳐지는 것은 아닙니다.
customer 10의 날짜순 구간
→ customer 20의 날짜순 구간
전체 날짜순
≠ 보장
8. Table Filter와 조기 종료
Index가 정렬 순서를 제공해도 Table Filter 때문에 N개보다 많은 후보를 확인할 수 있습니다.
SELECT order_id,
order_date,
amount
FROM orders
WHERE customer_id = :customer_id
AND status = 'COMPLETED'
ORDER BY order_date DESC,
order_id DESC
FETCH FIRST 20 ROWS ONLY;
Index:
(customer_id, order_date DESC, order_id DESC)
status가 Index에 없다면:
Index Entry 읽음
→ ROWID Table Access
→ status Filter
→ 탈락 가능
최근 주문 100건 중 완료 주문이 20건이면 20건을 반환하려고 약 100개 후보와 Table Row를 읽을 수 있습니다.
대안 Index:
(customer_id, status, order_date DESC, order_id DESC)
검토 기준입니다.
- status의 선택도·Skew
- 다른 Query의 Predicate
- Index 폭·DML 비용
- Covering 가능성
- 실제 후보 A-Rows·Table Buffers
9. Covering Index와 Top-N
다음 조회가 필요한 Column을 모두 Index에서 얻을 수 있다면 Table by ROWID를 생략할 수 있습니다.
(customer_id, order_date DESC, order_id DESC)
조회 Column:
customer_id, order_date, order_id
가능한 Plan입니다.
COUNT STOPKEY
INDEX RANGE SCAN DESCENDING ORDERS_CUST_DATE_IX
장점입니다.
- 정렬 생략
- Table Access 제거
- N건 확보 후 조기 종료 가능
Trade-off입니다.
- Index Column·Entry 폭 증가
- LEAF_BLOCKS 증가
- Buffer Cache 점유
- INSERT·UPDATE·DELETE 유지 비용
- Redo·Undo·공간 증가
한 Top-N SQL만 보고 무조건 Wide Covering Index를 만들지 않습니다.
10. Top-N 대상 Grain
Top-N을 Join 전으로 이동하면 업무 대상이 달라질 수 있습니다.
10.1 Join Row Top-N
SELECT o.order_id,
i.item_id,
o.order_date
FROM orders o
JOIN order_items i
ON i.order_id = o.order_id
ORDER BY o.order_date DESC,
o.order_id DESC,
i.item_id
FETCH FIRST 20 ROWS ONLY;
의미입니다.
주문·상품 조합 Row 중 상위 20행
10.2 주문 Top-N 후 Detail Join
WITH recent_order AS (
SELECT order_id,
order_date
FROM orders
ORDER BY order_date DESC,
order_id DESC
FETCH FIRST 20 ROWS ONLY
)
SELECT r.order_id,
i.item_id,
r.order_date
FROM recent_order r
JOIN order_items i
ON i.order_id = r.order_id;
의미입니다.
최근 주문 20건 선택
→ 각 주문의 모든 상품 반환
→ 최종 결과 20행 초과 가능
두 SQL은 1:N 관계에서 동등하지 않습니다.
10.3 Join Filter와 Top-N
“VIP 고객 주문 상위 20건”이라면 VIP Filter를 적용한 집합에서 순위를 정해야 합니다.
모든 주문 Top 20 선선택
→ VIP Join·Filter
≠
VIP 주문 집합
→ Top 20
Join·Filter가 Top-N 포함 집합을 바꾸는지 확인합니다.
11. OFFSET Pagination과 Keyset Pagination
OFFSET 방식입니다.
ORDER BY order_date DESC,
order_id DESC
OFFSET 100000 ROWS
FETCH NEXT 20 ROWS ONLY;
큰 Page로 갈수록 앞쪽 100,000행을 찾아 건너뛰는 비용이 커질 수 있습니다.
Keyset Pagination 예시입니다.
WHERE (
order_date < :last_order_date
OR (
order_date = :last_order_date
AND order_id < :last_order_id
)
)
ORDER BY order_date DESC,
order_id DESC
FETCH FIRST 20 ROWS ONLY;
장점입니다.
- 마지막으로 본 결정적 Key 뒤에서 탐색
- 적절한 Index에서 큰 OFFSET 처리 감소 가능
- Data 변경 중 상대적으로 Page 중복·누락을 줄일 수 있음
주의합니다.
- 정렬 Key 방향·NULL 의미를 정확히 구현
- Unique Tie-Breaker 필요
- 임의 Page 번호 직접 이동에는 별도 설계 필요
12. Top-N per Group
부서별 상위 급여 3명처럼 Group별 Top-N은 전체 FETCH FIRST와 다른 요구입니다.
SELECT employee_id,
department_id,
salary
FROM (
SELECT employee_id,
department_id,
salary,
ROW_NUMBER() OVER (
PARTITION BY department_id
ORDER BY salary DESC,
employee_id
) AS rn
FROM employees
)
WHERE rn <= 3;
핵심입니다.
전체 결과 Top 3
≠ 부서별 Top 3
ROW_NUMBER도 ORDER BY가 Total Order를 만들지 않으면 Tie Row의 번호가 비결정적일 수 있으므로 Unique Tie-Breaker를 사용합니다.
Oracle 26ai의 Partitioned Row Limiting Clause를 사용할 수 있는 환경도 있지만, 기존 Version 호환성과 업무 요구를 고려해 Analytic Function 방식과 비교합니다.
13. 실행계획 검증
실제 수행 통계를 수집합니다.
SELECT /*+ GATHER_PLAN_STATISTICS */
order_id,
customer_id,
order_date
FROM orders
WHERE customer_id = :customer_id
ORDER BY order_date DESC,
order_id DESC
FETCH FIRST 20 ROWS ONLY;
SELECT *
FROM TABLE(
DBMS_XPLAN.DISPLAY_CURSOR(
:sql_id,
:child_no,
'ALLSTATS LAST +MEMSTATS +PREDICATE +ALIAS +NOTE'
)
);
13.1 확인 항목
| 지표 | 질문 |
|---|---|
| Operation | COUNT STOPKEY·SORT ORDER BY STOPKEY·WINDOW NOSORT STOPKEY 중 무엇인가? |
| 하위 A-Rows | N건을 얻기 위해 후보를 몇 행 읽었는가? |
| Buffers·Reads | Index·Table·Full Scan에서 Block을 얼마나 읽었는가? |
| Starts | 하위 Operation이 반복됐는가? |
| Predicate | Access Predicate와 Table Filter 위치는 어디인가? |
| Used-Mem·Used-Tmp | Top-N Sort가 Memory·TEMP를 얼마나 사용했는가? |
| 결과 A-Rows | ONLY·WITH TIES·OFFSET 요구와 일치하는가? |
| Note | Transformation·Adaptive Plan이 있었는가? |
13.2 대표 비교
Plan A
COUNT STOPKEY
Index A-Rows 20
Table Buffers 25
Plan B
SORT ORDER BY STOPKEY
Full Scan A-Rows 50,000,000
Buffers 400,000
Sort Output 20
Plan A가 Top-N 조기 종료에 성공한 방향입니다.
하지만 다음 Plan도 가능합니다.
COUNT STOPKEY
Index 후보 A-Rows 500,000
Table A-Rows 20
Buffers 600,000
Index가 순서를 제공했어도 Table Filter 탈락이 크면 비효율일 수 있습니다.
14. First Row와 End-of-Fetch
Top-N 업무는 일반적으로 전체 대량 결과보다 First Page 응답이 중요합니다.
비교 조건을 통일합니다.
- 같은 Bind·Data Type
- 같은 N·OFFSET·WITH TIES
- 같은 결정적 ORDER BY
- 같은 Client Fetch Size
- 같은 Projection
- 같은 결과 Row
- 유사한 Cache 상태
측정합니다.
- 첫 Row 시간
- N번째 Row 시간
- End-of-Fetch 시간
- Buffers·Reads
- CPU
- TEMP
- 동시 실행 영향
Cost 숫자만으로 첫 Page 성능을 확정하지 않습니다.
15. 실전 적용 순서
1. Top-N 대상 Entity·Join Grain을 정의한다.
2. ONLY 또는 WITH TIES를 결정한다.
3. 결정적 ORDER BY와 Unique Tie-Breaker를 정한다.
4. ROWNUM Query Block 또는 FETCH FIRST 위치를 확인한다.
5. Predicate 후 후보 Row 수와 추가 Table Filter를 확인한다.
6. Index가 전체 정렬 순서를 제공하는지 검토한다.
7. COUNT·SORT STOPKEY와 하위 A-Rows를 확인한다.
8. Covering·복합 Index와 DML Trade-off를 비교한다.
9. OFFSET이 크면 Keyset Pagination을 검토한다.
10. 동일 결과·Bind·Fetch에서 First Row와 전체 Runtime을 검증한다.
자주 혼동하는 판단
| 혼동 | 정확한 기준 |
|---|---|
| ROWNUM <= N이면 항상 상위 N | 정렬과 Row 제한의 Query Block 위치 확인 |
| FETCH FIRST는 ORDER BY 없이도 안정적 | 결정적 ORDER BY 필요 |
| WITH TIES는 첫 Sort Key만 비교 | ORDER BY 표현식 전체의 Tie |
| 출력 N건이면 입력도 N건 | 하위 Access A-Rows·Buffers 확인 |
| STOPKEY가 있으면 Sort 없음 | COUNT STOPKEY와 SORT ORDER BY STOPKEY 구분 |
| SORT STOPKEY면 Table도 N건만 읽음 | 정렬되지 않은 입력은 전체 Scan 가능 |
| Index가 있으면 Sort 제거 | Prefix·방향·NULL·후속 Operation 확인 |
| Fast Full Scan이 정렬 순서 제공 | Fast Full Scan은 순서 보장 없음 |
| Top-N을 Join 전에 옮기면 항상 빠르고 동일 | 대상 Grain·Filter·중복 확인 |
| Cost가 가장 낮으면 첫 Page도 가장 빠름 | 동일 Fetch 계약의 Runtime으로 검증 |
개념 확인 문제
문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.
01Top-N 조회와 임의 N건 제한의 차이를 설명하시오.
Top-N과 임의 제한
- Top-N은 전체 후보에 업무 정렬 기준을 적용한 뒤 앞쪽 N건을 선택합니다.
- 임의 N건 제한은 Access Path에서 먼저 발견된 N건일 수 있으며 전체 상위 N건을 보장하지 않습니다.
02같은 Query Block에서 ROWNUM 조건과 ORDER BY를 함께 사용할 때 결과가 달라질 수 있는 이유를 설명하시오.
ROWNUM과 ORDER BY
- ROWNUM은 Row가 선택되는 과정에 부여됩니다.
- 같은 Query Block에서 ROWNUM으로 먼저 N건을 제한하면 ORDER BY는 선택된 N건만 재정렬할 수 있습니다.
- Access Path가 달라지면 선택되는 Row도 달라질 수 있습니다.
03ROWNUM Inline View Top-N의 기본 구조를 설명하시오.
Inline View 구조
- 안쪽 Query Block에서 결정적 ORDER BY로 전체 순서를 정의합니다.
- 바깥 Query Block에서
ROWNUM <= N을 적용합니다. - 예:
SELECT * FROM (SELECT ... ORDER BY ...) WHERE ROWNUM <= 10.
04FETCH FIRST의 ONLY와 WITH TIES 차이를 설명하시오.
ONLY·WITH TIES
- ONLY는 사용 가능한 Row가 충분하면 지정한 수만 반환합니다.
- WITH TIES는 마지막 Row와 모든 ORDER BY 표현식 값이 같은 추가 Row를 함께 반환하므로 N보다 많을 수 있습니다.
05결정적 ORDER BY와 Unique Tie-Breaker가 필요한 이유를 설명하시오.
결정적 정렬
- 경계에 동일 Sort Key Row가 있으면 어떤 Row가 포함되는지 비결정적일 수 있습니다.
- Unique ID 같은 Tie-Breaker를 추가하면 전체 Row 순서가 고정됩니다.
- ROW_NUMBER·Pagination에도 같은 원칙이 적용됩니다.
06COUNT STOPKEY와 SORT ORDER BY STOPKEY의 핵심 차이를 설명하시오.
두 STOPKEY
- COUNT STOPKEY는 이미 필요한 순서로 들어오는 Row Source를 N건 확보 후 중단할 수 있습니다.
- SORT ORDER BY STOPKEY는 정렬되지 않은 입력에서 상위 N개 후보를 유지하는 Sort이며 입력 전체를 읽을 수 있습니다.
07SORT ORDER BY STOPKEY 출력은 N건인데 하위 Full Scan이 전체 후보를 읽을 수 있는 이유를 설명하시오.
전체 후보 Scan
- 정렬되지 않은 입력에서는 마지막 후보에 더 큰 값이 있을 수 있습니다.
- 상위 N을 확정하려면 모든 후보의 Sort Key를 확인해야 할 수 있습니다.
- 따라서 Sort Output N과 하위 Access A-Rows는 다릅니다.
08Index Order Top-N에서 추가 Table Filter가 조기 종료를 지연시키는 이유를 설명하시오.
Table Filter
- Index가 순서대로 후보 RowID를 제공해도 Index에 없는 조건은 Table Row를 읽은 뒤 평가합니다.
- 탈락 Row가 많으면 N건을 반환하려고 N개보다 많은 Index Entry와 Table Block을 읽습니다.
09Join 전 Top-N 이동이 결과를 바꾸는 대표 사례를 설명하시오.
Join 전 Top-N
- 주문·상품 Join Row 상위 20행과 주문 20건을 먼저 선택한 뒤 모든 상품을 붙이는 결과는 다릅니다.
- VIP 고객 Filter처럼 Join 조건이 Top-N 포함 집합을 바꾸는 경우에도 선선택하면 올바른 Row가 누락될 수 있습니다.
10Top-N Plan을 실행 통계로 검증하는 절차를 설명하시오.
실행 통계 검증 - COUNT·SORT STOPKEY Operation을 확인합니다. - 하위 Index·Table·Full Scan의 A-Rows, Buffers, Reads, Starts를 확인합니다. - Access Predicate와 Table Filter를 구분합니다. - Used-Mem·Used-Tmp와 ONLY·WITH TIES 결과 행 수를 확인합니다. - 동일 Bind·정렬·Fetch 조건에서 첫 Row와 End-of-Fetch를 비교합니다.