1. Fundamentals of Oracle SQL
Oracle doesn’t know the data
the way you know it.
유 재 근
mail: naivety1@naver.com
2011.06.24
2. 목 차
• 정보시스템 개발과 SQL
• SQL Tuning 용어
• 분석 도구
• Join Method 개요
(NL Join, SM Join, Hash Join)
• 옵티마이징 전략
• 옵티마이저의 한계
3. Relational DBMS의 역사
• 2차 세계대전 동안 Royal Air Force에서 같이 지낸 동료 조종사와
승무원 그리고 옥스포드 학장께 이 책을 바칩니다. 이분들이야말
로 정부나 산업 그리고 통상분야에서 데이터베이스 관리의 관계형
접근에 모두들 반대했던 10년 아니 그 이상의 세월 동안 나의 신념
이 옳았다는 것을 위해 내 자신이 투쟁할 결심을 하게 해주셨습니
다.
- E.F.CODD The Relational Model for Database Management,
1990 –
• 1970 Dr. E.F. Codd. “A Relational Model for Large Shared Data
Banks”
RDB 모델을 제안
•1976 Peter Chen. “The Entity Relationship Model: Toward a
Unified View of Data” 개체 관계(ER) 모델 제안
• 1979 최초의 상용 DBMS ORACLE 출현
• 1983 IBM DB2 발표
• 1986 ANSI 데이터베이스를 다루는 언어인 SQL 표준 제정
4. 데이터베이스 모델 종류
(1) 계층형 (Hierarchical) 데이터베이스
• 데이터의 구조를 부모, 자식 관계로 계층적으로 표현
• 다:다 관계의 데이터 구조 표현 불가능
• 데이터 처리를 부모로부터 레코드를 건건이 읽어서 처리
• 세그먼트 구조 변환 시 항상 프로그램 재 컴파일이 필요함
(2) 네트워크형(Network) 데이터베이스
• 계층형 모형의 변형
• Owner-Member의 관계
• 두 레코드간 다 대 다 관계 : 3번째 레코드를 생성하여 두 레코드와의
Set로 정의
(3) 관계형(Relational) 데이터베이스
• 데이터 구조의 표현을 계층이 아닌 인스턴스간 연관성에 의해 표현
• 다:다 관계의 데이터 구조 표현 가능
• 미리 정의된 물리적인 연결이 없고, 실질적인 연결은 동적으로 이루어
짐
• 테이블 구조 변환 시 시스템의 나머지 부분에의 영향이 없음
• 데이터 처리는 집합(set)적으로 이루어짐
• 데이터의 질의(Query)가 자연어와 유사함
5. 정보시스템 개발 방법론
개발
방법론
구조적 방법론 정보 공학 방법
론
객체 지향 방법
론
컴포넌트 기반
방법론
연대 1960년대 ~
1980년대 중반
1980년대 중반 ~
1990년대 중반
1990년대 중반 ~
2000년대
1990년대 후반 ~
현재
주요
기술
환경
메인프레임 환경
단위업무 전산화
3세대 언어
파일/계층형 DB
소프트웨어 공학
클라이언트/서버
전사규모 전산화
4세대 언어
관계형 DB
통합 CASE
인터넷 환경
다양한 SW요구
객체지향 언어
대부분 관계형 DB
UML
웹서비스 환경
업무 기능단위컴포넌트
대부분 관계형
DB
UML
주요
기법
기능모형
자료흐름도(DFD)
구조적 프로그램
데이터 모형
실체관계도(ERD)
프로세스 계층도
Waterfall 개발
객체 모형
Use Case
Diagram
분석/설계 패턴
반복/ 점진 개발
컴포넌트
Class Diagram
컴포넌트 명세,
추출, 연동
아키텍쳐 설계
모델링 기능 모델링 데이터 모델링
프로세스 모델링
USE CASE 모델링
객체 모델링
USE CASE 모델
링
컴포넌트 모델링
7. Role & Responsibility
• Data Architect
Business Rule 분석, 데이터 구조 설계
논리적 데이터 모델링
• Database Administrator
DBMS설치, 물리적 공간 정의,
Index/Partition 설계, 통계정보 관리,
ACCESS PATH 관리
• Application 개발자
SQL활용하여 프로그램 개발
최적의 옵티마이징 전략에 의한 SQL문 작성
8. DBMS
• Database Management System
• 기업이 지속적으로 유지관리 해야 할 데이
터의 집합(Database)
• 방대한 양의 데이터를 편리하게 관리하고
효율적으로 저장하고 검색할 수 있는 환경
을 제공해 주는 시스템 소프트웨어(DBMS)
를 말한다.
9. Oracle Architecture
- 효율적인 SQL은 적은 량의 메모리와 DISK I/O를 발생한다.
- SQL문 수행 1)서버프로세스가 Shared Pool 검색 2) 없으면 데이터파일에서 dictionary 읽어옴 3) 옵티마이징 후 실행 4)
찾는 데이터가 없으면 데이터파일에서 메모리로 읽어들인다. 5)데이터버퍼캐시의 데이터를 client에 전달
암호
파일
인스턴스
DBWR
SMON
PMON CKPT
LGWR 기타
사용자
프로세스
서버
프로세스
PGA
제어
파일
데이터
파일
데이터베이스
리두 로그
파일
SGA
리두 로그
버퍼
공유 풀
데이터 딕셔너리
캐시
라이브러리
캐시
데이터베이스
버퍼 캐시
Java 풀 대용량 풀
매개변수
파일
아카이브된
로그 파일
10. SQL 실행
Parse
Bind
Execute
Fetch
SQL에 대한 구문분석과 Optimize
Bind 변수값이 있는 경우에 할당(Histogram 사용불가)
파싱 과정에서 만든 데이터 조회 경로를 이용하여 원하는
데이터를 버퍼 캐시 내에 위치시키는 작업
DML문에 대한 물리적 읽기 또는 논리적 읽기/쓰기 수행
필요한 경우 데이터에 대한 정렬
INSERT, UPDATE, DELETE는 이 단계에서 종료
Execute 결과값을 검색하여 반환, array 처리
User process가 요청한 SQL을 Server process 가 PGA를 통해 수행
11. Soft parse vs. Hard parse
같은 SQL(pcode)이 Shared pool에 있
는지?
SQL문에 포함된 모든 Object와
Column에 대한 Dictionary Validation
을 수행, 권한 체크
CBO or RBO, Optimal execution
plan 결정
Shared pool에 parse정보를 저장
SQL
Execute
Check syntax
Search shared SQL area
Search data dictionary
Optimizer
Save execution plan
Parse
Execute
Soft parse
Hard parse
14. Query Transformer 예제
Select department_id, salary
from employee
Where (department_id = 60 and salary = 4)
or (department_id = 60)
Select department_id, salary
from employee
Where department_id = 60;
15. Warming Up with some stretches
ACCESS PATH
- Index Stretegy, partition
JOIN METHOD
- NL JOIN, HASH JOIN, SORT MERGE JOIN, HASH_SJ, HASH_AJ……
JOIN ORDER
- emp dept, dept emp
Transformer (Logical Optimizer)
- Huristic Transformer / Cost Based Query Transformer
ETC
- null, not null, buffer pinning, OWI, filtering optimization, function,
case, decode, nvl, pagenation, ….
16. SQL 튜닝 이론
• Block I/O를 줄이는 방법
• 메모리 사용량을 줄이는 방법
17. DATA Modeling & Business Rule
INDEX현황 employees : (JOB_ID)
orders : (EMPLOYEE_ID, ORDER_DATE)
위 SQL을 어떻게 최적화 해야 할까?
18. DATA Modeling & Business Rule
• 요구사항
Employees 테이블의 job_id=‘J04’이면서 주문날짜(order_date)가
2012년01월01일 부터 2012년06월01일 범위 이며 주문상태
(order_status)가 ‘10’인 employee_id와 last_name을 출력하시오.
• Data modeling과 Business Rule을 모르면 최적의 SQL 작성 불가
능하다.
19. DATA Modeling & Business Rule
튜닝포인트
1. Employees 테이블에서 employee_id는 unique하다.
2. Orders 테이블 데이터(N개)를 모두 join할 필요가 없다.
3. 조건절을 만족하는 데이터 하나만 만나면 Join을 중단하자.
20. DATA Modeling & Business Rule
아쉽지만 11g에서는 Transformer가 위와 같이 튜닝전 SQL을 변경하지는 못한
다. 양심적인 개발자(인간)가 SQL을 잘 만들어야 한다.
21. What is your DB management
level?
• Level 1
DB에 이상이 발생하면 조치한다.
• Level 2
주기적으로 모니터링 한다.
• Level 3
DB를 평소에 건강하게 관리한다.
- ACCESS PATH를 관리한다.
실행계획을 관리한다.
22. Application 프로그램 vs. SQL
• 프로그램은 로직이 보인다.
• SQL은 처리과정이 드러나 있지 않다.
(10053 Trace file을 보면 알 수 있다.)
• 옵티마이저를 이해하고, 훈련을 해야 한다.
24. DBMS_XPLAN.DISPLAY_CURSOR
• Grant select on v_$session to scott;
• Grant select on v_$sql_plan_statistics_all
to scott;
• Grant select on v_$sql to scott;
사용 방법
1. Alter session set statistics_level = all;
2. /*+ gather_plan_statistics */
25. 사용 예제
select /*+ gather_plan_statistics */ c4, c5, c6
from subquery_t1 t1
where c6 >= :b1 and c6 <= :b2
and exists ( select /*+ UNNEST */ --조인방식하도록 NO_UNNEST를 제거
'x'
from subquery_t2 t2
where t2.c1 = t1.c4
and t2.c3 >= :b3 and t2.c3 <= :b4);
select * from table(dbms_xplan.display_cursor(null,null,'allstats last advanced'));
26.
27. Plan_hash_valu
e
같은 SQL_ID라도 실행계획이 변경된다면 plan_hash_value가 변경이 된다.
Id 순서대로 부여되는 번호
Operation 실행 Operation 명
Name 사용되는 Object 명
Starts 실행 횟수. NL Join이나 SM 조인에서 선행 데이터 건수
E-Rows 실행 단계별 예상 건수. 옵션에 –rows 를 사용하면 안나타남
A-Rows 실행 단계별 실제 건수
A-Time 실행 단계별 걸린 시간. 누적 값이기 때문에 해당 라인에서의 수행 시간을 알고 싶
다면 이전 단계의 A-Time 값을 빼야 한다.
Buffers Logical I/O(Buffer Cache에서 읽어 들임) 통계. 누적 값
Reads I/O(디스크에서 읽어 들임)통계. 누적 값
OMem PGA 사용 operation에서 OPTIMAL일 때 예상되는 PGA사용량
1Mem PGA를 사용 operaion에서 onepass일 때 예상되는 PGA사용량
Used-Mem PGA를 사용하는 operation에서 실제 사용된 PGA메모리 양.
ONE PASS로 수행되면(1)로 나타나도 (0)은 optimal로 수행됨.
28. 위에서 Query Block 이름이 하나이므로, 옵티마이저가 Query Transformation
을 수행하여 처리했음을 알 수 있다.
29. ORACLE이 SQL을 수행하
면서 내부적으로 사용한
HINT들의 목록
실행계획의 특정 단계
에서 어떤 Column을
추출하는가를 보여준
다.
Access Predicate : Access Type을 결정하
는 사용되는 predicate(조건)를 의미.
실제 Block을 읽기 전에 어떤 방법으로
Block을 읽을 것인가를 결정. Index
Lookup이나 Join등은 access predicate로
표현된다.
Filter Predicate : 실제 Block을 읽은 후
Data를 걸러내기 위해 사용되는
predicate를 의미한다.
30. <실행통계 FORMAT>항목
BASIC Operation 명과 그 옵션만을 보여준다.
TYPICAL Partition과 parallel 사용과 같은 관련된 다양한 정보를 보여준다.
기본값임
SERIAL TYPICAL과 같으나 parallel 정보가 제외된다.
ALL 보여줄 수 있는 정보를 다 보여준다.
Query Block Name / Object Alias section / the predicate
section / the column projection section
ADVANCED ALL + outline 및 바인드 변수 정보 세션을 보여준다.
LAST 최근에 실행된 커서에 대한 실행 통계를 보여줌
OUTLINE 실행계획에서 재상산될 힌트의 집합을 보여줌
PREDICATE Predicate 섹션을 보여준다
IOSTATS 커서 실행에 대한 I/O 통계를 보여줌
BYTES 계산된 bytes 수를 보여줌
COST Optimizer 에 의해 계산된 cost
36. 10053 Event
• Physical Optimization과 Logical Optimization에 대해 가장 상세한
Trace를 생성함
• Access Path, Join Method, Join Order를 알 수 있다.
• Query Transformation의 동작을 추적할 수 있다.
• 10053 Event를 발생시키는 방법
ALTER SESSION SET EVENTS ‘10053 trace name context forever,
level 1’;
내가 작성한 SQL문 수행
ALTER SESSION SET EVENTS ‘10053 trace name off’;
• Trace File 생성 경로
user_dump_dest 파라미터에 정의되어 있는 디렉토리에 생성
• Trace file sample : 첨부파일 참조
37.
38. 실행 계획 순서 분석
• 가장 안쪽 레벨에서 바깥쪽 레벨 순서로 읽는다.
• 같은 레벨이 있다면 위쪽부터 아래로 읽는다.
• 위에서 2번과 3번이 같은 집합이므로 하나로 보고, 4번과 5번이 같은 집합이므
로 하나로 본다.
• 3 2 5 4 1
• 위에서 E-Rows 와 A-Rows가 같으므로 Optimizer의 판단이 최적일 가능성 많음
39. ID Operation Name
0 SELECT STATEMENT
1 NESTED LOOPS
2 TABLE ACCESS FULL EMPLOYEES
3 TABLE ACCESS BY INDEX ROWID DEPARTMENTS
4 INDEX UNIQUE SCAN IX_DEPARTMENTS_PK
옛날방식
(8i)의 NL
JOIN
• 가장 안쪽 레벨에서 바깥쪽 레벨 순서로 읽는다.
• 같은 레벨이 있다면 위쪽부터 아래로 읽는다.
• 위에서 2번이 하나의 집합, 3번과 4번이 하나의 집합
• 2 4 3 1
• 위에서 E-Rows 와 A-Rows가 같으므로 Optimizer의 판단이 최적일 가능성 많음
40. ID Operation Name
0 SELECT STATEMENT
1 NESTED LOOPS
2 TABLE ACCESS FULL EMPLOYEES
3 TABLE ACCESS BY INDEX ROWID DEPARTMENTS
4 INDEX UNIQUE SCAN IX_DEPARTMENTS_PK
NLJ_PREFETCH
• 3 4 2 1
• LEADING(A B) A집합을 먼저 읽어라.
• USE_NL(B) Nested Loop 조인방법을 써라
• NO_NLJ_BATCHING(B) 11g New Feature인 Batching NLJ을 사용하지 말라.
• NLJ_PREFETCH : rowid에 의한 테이블 access를 건건이 하는 것이 아니라 여러
개(운반단위) 모든 다음 한번에 block을 read한다.
- 새로쓴 대용량 데이터베이스 솔루션 : Advanced Nested Loop Join
- Jonathan Lewis, CBO Fundamentals : Table Prefetching
9i, 10g 버전에서의 실행계획
옛날방식
(8i)의 NL
JOIN
41. • 3 4 2 5 1
• NLJ_BATCHING(B) 11g New Feature
• NLJ_BATCHING : 후행 테이블의 Index Scan 시에도 Index에 대한 Prefetch 가
이루어진다.
NLJ_BATCHING 11g 버전에서의 실행계획
앞으로의 설명에서는 NJ_JOIN 시에 Prefetch 기능은 고려하지 않고 전통적
인 NL Join방식을 기준으로만 설명할 것이다.
42. Optimizer가 판단해서 전통적인 NL방식, NLJ_PREFETCH, NLJ_BATCHING를 선
택한다. 어떤 NLJ방식을 사용한 건지 헷갈리면 Outline 부분의 힌트를 참조
57. NESTED LOOP
TAB1 TAB2
INDEX
(KEY2)
KEY1 = KEY2
TABLE ACCESS
BY ROWID
운반
단위
o
o
o
x
COL1 = ’10’
FLD2
LIKE
‘ABC%’
x
INDEX
(FLD1)
FLD1=‘111'
TABLE
ACCESS BY
ROWID
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
1. FLD1 컬럼에 INDEX가 없다면?
2. KEY2 컬럼에 INDEX가 없다면?
58. SORT MERGE JOIN
TAB1 TAB2
운반단위
KEY1= KEY2
머지 조건으로
.
.
.
.
.
.
.
.
.
.
.
.
S
O
R
T
INDEX
(COL1)
COL1='10'
TABLE
ACCESS
BY ROWID
.
.
.
.
.
.
.
.
.
FLD2
LIKE
‘ABC%’
x
S
O
R
T
FLD1=‘111'
TABLE
ACCESS
BY ROWID
INDEX
(FLD1)
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
1. KEY1 컬럼과 KEY2 컬럼에 INDEX 존재 여부가 영향이 있나?
59. HASH JOIN
운반단위
HASH
FUNCTION
PARTITION
TABLE
HASH
TABLE
BITMAP
VECTOR
C31
C21
C41 C51
TAB1
HASH AREA UGA
C11
P P
P P P
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
HASH
FUNCTION
TAB2
선행테이블(BUILD INPUT)을 PGA 메모리에 HASH TABLE로 생성 후 후행 테이
블을 SCAN하면서 PGA에서 컬럼 매핑하는 방식으로 수행한다.
60. 실행 계획 패턴
옵티마이저는 거의 대부분 다음의 실행계획 패턴으로 수행
NESTED LOOPS
NESTED LOOPS
TABLE ACCESS (BY INDEX ROWID) OF ‘SDAMASTER.SAM_ORG’
INDEX (UNIQUE SCAN) OF ‘SDAMASTER.PK1.SAM_ORG’
TABLE ACCESS (BY INDEX ROWID) OF ‘SDAMASTER.SAM_STF’
INDEX (RANGE SCAN) OF ‘SDAMASTER.INS_INS_PL’
TABLE ACCESS (BY INDEX ROWID) OF ‘SDAMASTER.INS_INS_PL’
INDEX (SKIP SCAN) OF ‘SDAMASTER.I02_INS_INS_PL’
NESTED LOOP 조인 패턴
61. 실행계획 패턴
SORT MERGE 조인 패턴
TABLE ACCESS FULL OF ‘사원’
SORT (JOIN)
VIEW
SORT (UNIQUE)
TABLE ACCESS BY ROWID OF ‘근태’
INDEX RANGE SCAN OF ‘유형_일자_IDX’
HASH 조인 패턴
HASH JOIN
TABLE ACCESS (BY INDEX ROWID) OF ORDER
SORT (JOIN)
INDEX(RANGE SCAN) OF ORDDATE_INDEX (NON-UNIQUE)
TABLE ACCESS (FULL) OF DEPT
조인은 반드시 성공한 결과가 다음 조인에 참여
조인 테이블이 무수히 많아도 테이블을 액세스하는 방법은 2가지만 존재
62. 실행계획 패턴
복잡하지만 단위 별로 분석하면 앞에 설명한 기본적인 패턴을 벗어나지 못함
ROWS EXECUTION PLAN .
0 SELECT STATEMENT
1181 SORT (GROUP BY)
1181 NESTED LOOPS
1514 VIEW
256854 SORT (GROUP BY)
256854 HASH JOIN (OUTER)
256854 VIEW
256854 UNION-ALL
256852 NESTED LOOPS
0 INLIST ITERATOR (CONCATENATED)
256856 TABLE ACCESS (BY INDEX ROWID) OF ‘DPACCB’
256908 INDEX (RANGE SCAN) OF ‘DPACCB_IDX1’ (NON-UNIQUE)
24915032 TABLE ACCESS (BY INDEX ROWID) OF ‘BR_INFO’
40840104 INDEX (RANGE SCAN) OF ‘BR_INFO_IDX2’ (NON-UNIQUE)
0 INLIST ITERATOR (CONCATENATED)
422116 TABLE ACCESS (BY INDEX ROWID) OF ‘DPACCB’
422118 INDEX (RANGE SCAN) OF ‘DPACCB_IDX2’ (NON-UNIQUE)
15 VIEW
15 SORT (GROUP BY)
15 TABLE ACCESS (BY INDEX ROWID) OF ‘DPDDBS’
16080201 INDEX (RANGE SCAN) OF ‘DPDDBS_IDX1’ (NON-UNIQUE)
1688 TABLE ACCESS (BY INDEX ROWID) OF ‘DPGDPF’
3202 INDEX (RANGE SCAN) OF ‘PK_DPGDPF’ (UNIQUE)
63. OUTER JOIN
두 개의 테이블 조인시 한쪽 테이블(기준테이블)의 row에 대하여 다른 쪽
테이블에 일치하는 row가 없더라도 다른 쪽 테이블의 row를 NULL로
하여 select하는 조인 기법
1. NL JOIN일 경우 무조건 A집합을 driving해야 한다.
2. HASH JOIN일 경우에는 SWAP_JOIN_INPUTS 힌트로 B테이블을 BUILD
INPUT 테이블로 만들 수 있다.
64. SEMI JOIN
TAB1 TAB2
INDEX
(KEY2)
KEY1 = KEY2
TABLE ACCESS
BY ROWID
운반
단위
o
o
o
x
COL1 = ’10’
FLD2
LIKE
‘ABC%’
x
INDEX
(FLD1)
FLD1=‘111'
TABLE
ACCESS BY
ROWID
SELECT *
FROM TAB1 A, TAB2 B
WHERE A.KEY1 =
B.KEY2
AND A.FLD1 = ‘111’
AND A.FLD2 LIKE ‘ABC’
AND B.COL1 = ’10’ ;
“반조인”
선행Table의 Row가 후행Table
의 Row와 Match되기만 하면
즉각 Join이 만족된 것으로
간주하고 해당 Row에 대해서
는 더 이상의 탐색을 진행하지
않는다.
Semi Join은 Exists 와 In
Operation의 효율적인 처리를
위해 고안된 Join 방식이다.
69. 조인 순서와 효율
힌트를 제거했을때 옵티마이저가 판단한 최적의 실행계획
IX_DEPARTMENTS_PK 인덱스 사용시 Index Fast Full Scan을 하지 않은 이
유는 정렬을 보장하기 위해서임.
INDEX FULL SCAN : single block I/O
INDEX FAST FULL SCAN : multi block I/O
EMPLOYEES 집합은 TABLE FULL로 읽은 후 department_id기준으로 Sorting
74. 어? DISK I/O는 29 block인데, Memory I/O는 4개 block밖에 안되네?
75. • CUSTOMER_ID 조건을 넣었더니, 결과 건수는 같은데 일량(database
buffer cache 읽는 수)은 4개 1651개로 증가했다.
• 처리 시간은 0.03 0.06 으로 길어졌다.
• 총 디스크 블록 수가 6494 이므로 전체 테이블의 20% 정도를 읽은 후 10
건을 추출했음을 알 수 있다.
76. 부분 범위 처리 시사점
• 조건에 해당하는 데이터 건수의 비율이 높
으면 높을수록 부분 범위 처리에 대한 성
능은 높아진다.
• 조회 조건에 의해서 FILTERING해야 될 건
수가 많을 수록 많은 block을 Scan해야 하
기 때문에 rownum 조건을 만족하는 부분
범위 처리에 대한 성능은 떨어진다.
77. PAGENATION 처리 문법
• SELECT A.*
FROM (SELECT ROWNUM AS RN, A.*
FROM (……….
……….) A
WHERE ROWNUM <= :b2
) A
WHERE RN >= :b1
78.
79. • (ORDER_DATE, ORDER_MODE, EMPLOYEE_ID) 인덱스를 사용하여 SORT가 발생
하지 않았다.
• 하지만 위 SQL은 부분범위 처리를 하지 못하고 INDEX 1874건을 모두 읽어서
처리하고 맨 마지막에 10건을 FILTERING 처리하고 있다.
• 앞 SLIDE에서 제시한 PAGENATION 문법을 따라야 부분범위 처리가 가능하다.
80. • (ORDER_DATE, ORDER_MODE, EMPLOYEE_ID) 인덱스를 10건만 SCAN하고 멈추
었다.
• 최적의 인덱스 : ORDER BY절에 해당하는 컬럼이 INDEX 컬럼으로 모두 존재
• SORT ORDER BY OERATION이 발생하지 않았다.
81. 최적의 INDEX가 없는 경우
IX_ORDERS_N2 : (EMPLOYEE_ID, ORDER_DATE)
• 최적의 INDEX가 없기 때문에 IX_ORDERS_N2 인덱스를 이용했으며, 인덱스를
1874건을 읽은 후에야 조건을 만족하는 10건을 추출할 수 있었다.
• SORT ORDER BY STOPKEY 오퍼레이션은 10칸의 배열을 만들어 놓고 ORDERS
테이블에서 ORDER_DATE로 SORT한다.
성능개선하려면 어떻
게 해야 할까?
82. • CUSTOMERS 테이블을 OUTER JOIN하고 있기 때문에 CUSTOMERS 테이블은
결과 건수에 아무 영향을 미치지 않느다.
• 위 실행계획은 ORDERS와 CUSTOMERS를 JOIN한 후에 SORT를 하고 있다.
• 따라서 CUSTOMERS의 IX_CUSTOMERS_PK를 1874번 반복 access하고 있다.
• 조인하기 전에 ORDERS 집합에서 10건을 추출 후 CUSTOMERS집합과 JOIN을
하면 CUSTOMERS는 10번만 access할 것이다.
83.
84. • 7 6 5 4 3298 1
• 최적의 인덱스가 없기 때문에 SORT ORDER BY STOPKEY는 없앨 수가 없다.
• ORDERS 집합을 먼저 pagenation처리하였고, 그 결과 집합(VIEW)을
CUSTOMERS집합과 LESTED LOOPS OUTER 조인 수행하였다.
• 만약 CUSTOMERS 테이블과의 조인이 INNER JOIN이라면 조인 했을 때 건수
가 줄어들 수도 있기 때문에 위와 같은 방법을 항상 사용할 수 있는 것은 아니
다.
85.
86. 첫 페이지(1번 row ~ 10번 row까지)를 LOADING하는 SQL의 실행계획
• 최적의 인덱스(ORDER_DATE)가 있어서 SORT ORDER BY STOPKEY가 발생하
지 않아서 최적의 건수만 읽었기 때문에 비효율이 없다.
• JOIN I/O를 줄이기 위해서 CUSTOMERS 집합과 조인하기 전에 PAGING 처리
를 하였다.
• :PAGENUM 바인드 변수 값을 1000으로 변경(즉, 1000 page의 데이터를 보겠
다는 의미임. 10001 ~ 10010의 row를 보겠다)하면 실행계획이 아래와 같다.
87. PAGE_NUM 변수값이 커질수록(뒤 페이지 조회) A-Rows가 커진다. 하지만 늘
어나는 A-Rows에 비해서 발생 I/O는 크게 낮다.
실제 사용자가 1000 PAGE까지 클릭해서 보는 일은 드물 것이다.
88. INDEX 전략의 중요성
SELECT *
FROM TAB1
WHERE A = '10'
AND B = '941005'
AND C = '123'
AB C
INDEX1 INDEX2
INDEX1
만 사용
AB = '10'||'941005'
C = '123'
ABD C
INDEX1 INDEX2
D column
추가
ABD LIKE '10'||'941005'||'%'
C = '123' INDEX2
만 사용
89. 효율 적인 SQL 작성 선행 조건
• 설계가 부실하면 SQL만으로 성능 향상에
한계가 있음
• 최적의 접근 경로 파악을 근거로 종합적이
고 전략적인 차원에서 데이터 구조와 인덱
스 설계를 해야 함
90. SUMMARY
• Cardinality and Clustering determine
whether the “Big Job” or “Small Job”
strategy should be preferred
• If the optimizer gets these estimates rigtht,
the resulting execution plan will be
efficient within the boundaries of the given
access paths
• Know your data and business questions
• Help your optimizer. (Oracle doesn’t know
the data the way you know it.)