47
IT 역역역역 역역 역역역역 SQL 역역역역 2 역역 역역역역역 3 역 역역역 역역역 역역 역역역 역역역 역역역역역 .

효율적인Sql작성방법 2주차

  • Upload
    -

  • View
    698

  • Download
    9

Embed Size (px)

Citation preview

Page 1: 효율적인Sql작성방법 2주차

IT 역량강화 과정효율적인 SQL 작성방법2 주차

시스템개발 3 팀 강희동본서의 모든 이미지 출처는 생략합니다 .

Page 2: 효율적인Sql작성방법 2주차

ROW ID 조인 시 순서 ROWID 구조

블록간에 유일한 구분 값을 위해 블록 주소 정의ORACLE 에서 INDEX 를 생성하기 위해 내부적으로 사용하는 키로 임의 변경 , 삭제 불가 ROWID 는 테이블 형태로 관리 되지 않고 식별키로만 사용테이블 ROW 에 접근하는 가장 빠른 수단테이블 열 들을 (ROWS) 위한 유일한 식별자

Page 3: 효율적인Sql작성방법 2주차

ROW ID 조인 시 순서

SELECT ROWID, MBR_ID FROM MBR_MEMBER_MST

AAAX5JAARAAB83rAAJ 1000457AAAX5JAAQAAChKRAAp 1000492AAAX5JAAQAAChR4AAR 1001132AAAX5JAARAAB87sAAe 1001135AAAX5JAARAAB82qAAn 1001144AAAX5JAARAAB82rAAI 1001505AAAX5JAAQAAChU7AAa 1001558AAAX5JAAQAAChU7AAY 1001565

SELECT ROWID, MBR_ID FROM COM_LOGIN_MST

AAAXpyAAQAACgW-bAAB jangreenAAAXpyAAQAACgW-bAAC ngh8751AAAXpyAAQAACgW-bAAD 70533545AAAXpyAAQAACgW-bAAE oji1602AAAXpyAAQAACgW-bAAF chong1210AAAXpyAAQAACgW-bAAG shin0420AAAXpyAAQAACgW-bAAH kjs89AAAXpyAAQAACgWbAAI choeun90

SELECT ROWID, A.MBR_ID, B.LOGIN_ID FROM MBR_MEMBER_MST A, COM_LOGIN_ID_MST B WHERE A.MBR_ID = B.MBR_ID

SELECT A.ROWID, B.ROWID A.MBR_ID, B.LOGIN_ID FROM MBR_MEMBER_MST A, COM_LOGIN_ID_MST B WHERE A.MBR_ID = B.MBR_ID

Page 4: 효율적인Sql작성방법 2주차

ROW ID 조인 시 순서

SELECT ROWID, A.* FROM (

SELECT A.ROWID, B.ROWID A.MBR_ID, B.LOGIN_ID FROM MBR_MEMBER_MST A, COM_LOGIN_ID_MST B WHERE A.MBR_ID = B.MBR_ID

) A

SELECT ROWID, A.* FROM (

SELECT A.MBR_ID, B.LOGIN_ID FROM MBR_MEMBER_MST A, COM_LOGIN_ID_MST B WHERE A.MBR_ID = B.MBR_ID

) A

AAAXpyAAQAACgW-bAAB 167132 jangreenAAAXpyAAQAACgW-bAAC 187917ngh8751AAAXpyAAQAACgW-bAAD 18398870533545AAAXpyAAQAACgW-bAAE 160764oji1602AAAXpyAAQAACgW-bAAF 186335chong121

0AAAXpyAAQAACgW-bAAG 161908shin0420AAAXpyAAQAACgW-bAAH 177346kjs89AAAXpyAAQAACgWbAAI 165904choeun90

A BAAAX5JAANAAHwjkAAV AAAXpyAAQAACgW-

bAAB 167132 jangreenAAAX5JAANAAH-wjkAAW

AAAXpyAAQAACgW-bAAC 187917 ngh8751

AAAX5JAANAAH-wjkAAX

AAAXpyAAQAACgW-bAAD 183988 70533545

AAAX5JAANAAHwjkAAY AAAXpyAAQAACgW-bAAE 160764 oji1602

AAAX5JAANAAHwj-nAAb

AAAXpyAAQAACgW-bAAF 186335 chong121

0AAAX5JAANAAHwjnAAc AAAXpyAAQAACgW-

bAAG 161908 shin0420AAAX5JAANAAHwj-nAAd

AAAXpyAAQAACgW-bAAH 177346 kjs89

AAAX5JAANAAHwj-nAAe AAAXpyAAQAACgWbAAI 165904 choeun90ROWID 가 작은게 출력

Page 5: 효율적인Sql작성방법 2주차

서브쿼리가 비효율적 인가 ?

실행 계획을 볼 줄 알면 서브쿼리가 비효율적으로 나올 수 없습니다 .

서브쿼리는 집합으로 묶어주는 기능일 뿐이지 성능을 비효율적으로 만들지 않습니다 .

멀티캐시 효과 때문에 경우에 따라 오히려 퍼포먼스를 낼 수 있습니다 .

서브쿼리는 읽는 범위가 작아야 합니다 .

Page 6: 효율적인Sql작성방법 2주차

서브쿼리가 비효율적 인가 ?

SELECT DEPT_NO, COUNT(*) CNT, (SELECT COUNT(*) FROM EMP) TOTALEMP FROM EMPGROUP BY DEPT_NO

변경 후SELECT DEPTNO, DNAME ,TO_NUMBER(SUBSTR(VAL, 1,10)) AVG_SAL ,TO_NUMBER(SUBSTR(VAL, 11,10)) MIN_SAL ,TO_NUMBER(SUBSTR(VAL, 21)) MAX_SAL FROM ( SELECT D.DEPTNO, D.DNAME, (SELECT LPAD(AVG(SAL),10)||LPAD(MIN(SAL),10)||MAX(SAL) FROM EMP

WHERE DEPTNO = D.DEPTNO)VAL FROM DEPT D WHERE D.LOC = 'LA' )

안 좋은 예 )

테이블은 최대한 한번만 읽어서 처리 !

변경 전SELECT D.DEPTNO, D.DNAME. AVG_SAL, MIN_SAL, MAX_SAL FROM DEPT D, (SELECT DEPTNO, AVG(SAL) AVG_SAL, MIN(SAL) MIN_SAL, MAX(SAL) MAX_SAL FROM EMP GROUP BY DEPTNO)E WHERE E.DEPTNO(+) = D.DEPTNO AND D.LOC = 'LA'

- 불필요한 사원 집합 발생-OUTER JOIN 으로 인한 E 드라이빙- 사원 테이블에 넓은 영역 집합 함수

- 효율적인 사원 집합 추출-OUTER JOIN 을제거하여 D 부터 드라이빙- 사원 테이블에 좁은 영역에 집합 함수- 서브쿼리를 CONCATENATE 사용

Page 7: 효율적인Sql작성방법 2주차

1 주차 Review

Page 8: 효율적인Sql작성방법 2주차

Programming vs SQL

Programming

SQL

public int aa(int a, int b)throws Exception{int c = 0;if(a == b){

return a;}else{

return b;}

}

public String getMaxNumber(int iNum1, int iNum2)throws Exception{return iNum1 > iNum2 ? iNum1 : iNum2;

}

SELECT * FROM (

SELECT ROWNUM RN , A.* FROM EMP AWHERE ENAME LIKE ‘ 강 %’ AND JOB <> ‘SALES’ AND (STATUS = ‘1’ OR STATUS = ‘2’)

)WHERE RN BETWEEN 1 AND 10

SELECT * FROM

(SELECT ROWNUM RN , A.* FROM EMP AWHERE ENAME LIKE ‘ 강 %’ AND NOT EXISTS(SELECT 1 FROM EMP B WHERE B.EMPNO = A.EMPNO AND JOB = ‘SALES’ AND ROWNUM = 1) AND STATUS IN (‘1’, ‘2’) AND ROWNUM <= 10

) WHERE RN >= 1

Page 9: 효율적인Sql작성방법 2주차

절차형 사고 버리기

Flow chart

ProgrammingScript

Schedule절차형 사고 버리기 집합 사고를 키우세요

SELECT * FROM MNS A, SKP B, SKT C WHERE A. 조건 = B. 조건 AND B. 조건 = C. 조건 AND C. 조건 = ‘1234’

Page 10: 효율적인Sql작성방법 2주차

Driving 의 중요성

TABLE1 TABLE2 TABLE3

(10000 row)

(1000 row)

(2 row)

. . .

1 A2 C3 D4 K5 M6 F7 E8 M. . . .. . . .

A 가P 나C 라H 사 . . .E 마

라 10마 20

최소 10,000 회 이상 ACCESS

TABLE3 TABLE2 TA-BLE1

(10000 row)

(2 row)

라 10마 20

(1000 row)

A 가P 나C 라S 마 . . .E 마

1 A2 C3 D4 K5 M6 F7 E8 M. . . .. . . .

최대 6 회 이하 ACCESS

Page 11: 효율적인Sql작성방법 2주차

Driving 의 중요성TABLE1 TABLE2 TABLE3

(10000 row)

(1000 row)

(2 row)

. . .

1 A2 C3 D4 K5 M6 F7 E8 M. . . .. . . .

A 가P 나C 라H 사 . . .E 마

라 10마 20

-TABLE1 을 무조건 읽어야 한다면 그 다음에 올 DRIVNING 순서를 예측- 똑같은 조건 이라면 M 이 아닌 1 부터 DRIVING

TABLE1 TABLE3 TA-BLE2

(1000 row)

(10000 row)

(2 row)

. . .

1 A2 C3 D4 K5 M6 F7 E8 M. . . .. . . .

C 10E 20

A 가P 나C 라S 마 . . .E 마

인덱스 조인 조건 확인 !!!!!!

Page 12: 효율적인Sql작성방법 2주차

Optimizer

select col1, col2*10, . . from account x, custommer y, transection zwhere x.acct = z.acct and y.cust = z.cust and jdate = ‘130319’;

SQL OPTIMIZER

DATA Dictionary

SQL해석

COL$

IND$

OBJ$

TAB$

VIEW$

참조

실행

customer

transaction

account

DATA

추출

실행계획작성

참조

ㄴㅍㄴㅇㄹㅇㄹㄴ 률ㄷㄱ 34346ㅓㅏㄴ아ㅓㅗㄴㅇ ㅓㅜㄴ야ㄷㅈㄷㅂ저

ㅊ리아ㅡㄹ ㅏㅡ치ㅏ ㅜ ㅓ투 93ㅑㅇ너ㅓㅇㄹ너ㅐㅇ러ㅐㄿㄹㅇㄹ ㅓㅜㄴ ㅑ

ㅑㅕㅜㅑ ㅜ랸웅ㄴ

ㅑ어ㅐ우ㅐㅇ눈애ㅓ래ㅓㅐ앵래 8 ㅈ 9 ㅗ 9 ㅗㅑ야 ㅏㄴ어ㅐ

B BB JHBJB M M J ㅐㅜ ㅜㄹ울

애ㅣㅓ애럴애ㅓㄹ애 ㅐ

ㄹ앙ㄹㄹ이ㅏㅡㅈ냐ㅈㄷㅂ 989 ㅈ돌ㅍㄴㅇㄴ

ㄴ어ㅐㅑㅓ내ㅑ

ㄴㅍㄴㅇㄹㅇㄹㄴ 률ㄷㄱ 34346 ㅓㅏㄴ아ㅓㅗㄴㅇ ㅓㅜㄴ야ㄷㅈㄷㅂ저

ㅊ리아ㅡㄹ ㅏㅡ치ㅏ ㅜ ㅓ투 93 ㅑㅇ너ㅓㅇㄹ너ㅐㅇ러ㅐㄿㄹㅇㄹ ㅓㅜㄴ

ㅑㅕㅇ ㅑㅕㅜㅑ ㅜ랸웅ㄴ

ㅑ어ㅐ우ㅐㅇ눈애ㅓ래ㅓㅐ앵래 8 ㅈ 9 ㅗ 9 ㅗ

ㅑ야 ㅏㄴ어ㅐㅑ퍼ㅐㅜ ㅜㄹ울

애ㅣㅓ애럴애ㅓㄹ애 ㅐ

ㄹ앙ㄹㄹ이ㅏㅡㅈ냐ㅈㄷㅂ

사용자는 요구만 하고 OPTIMIZER 가 실행계획 수립

수립된 실행계획에 따라 엄청난 수행속도 차이 발생

실행계획 제어가 어렵다 .

OPTIMIZER 가 좋은 실행계획을 수립할 수 있도록 종합적이고 전략적인 FAC-TOR 를 부여

비절차형으로 기술해야 함 집합적으로 접근해야 함

Page 13: 효율적인Sql작성방법 2주차

Optimizer

SQL Pars-ing

Optimiza-tion

Row-Source Execution

Parser OptimizerRow-SourceGenerator SQL EngineParsed

SQLExecution Plan

Row-Source

1.Query Trans-former2.Estimator3.Plan Generator

Page 14: 효율적인Sql작성방법 2주차

Optimizer

SELECT * FROM EMP WHERE ENAME LIKE 'AB%' AND EMPNO = '7890'

SELECT * FROM EMP WHERE ENAME LIKE 'AB%' AND JOB LIKE 'SA%'

Rulebased

Costbased

SELECT * FROM EMP WHERE ENAME LIKE 'AB%' AND EMPNO = '7890'

SELECT * FROM EMP WHERE ENAME LIKE 'AB%' AND JOB LIKE 'SA%'

SELECT * FROM EMP WHERE JOB = 'SALESMAN' AND EMPNO = '7890'

나중에 생성된

Index 사용

SELECT * FROM EMP WHERE JOB = 'SALESMAN' AND EMPNO = '7890'

분포도에 따라 ENAME index

도 사용

INDEX merge (and_equel),

특정 index

분포도에 따라 index 사용 ,

혹은 full scan

항상 EMPNOIndex 만 사용

INDEX merge(and_equel)

Page 15: 효율적인Sql작성방법 2주차

전체범위 VS 부분범위

전 체 범 위 처 리

2차가공

운반단위

• • • •

1차스캔

Full Range Scan 후 가공하여 Array Size 만큼 추출

부 분 범 위 처 리

2차가공

운반단위

1차스캔

조건을 만족하는 Row 수가 Ar-ray Size 에 도달되면 멈춤

Page 16: 효율적인Sql작성방법 2주차

전체범위 VS 부분범위

2

차가공

운반단위

TAB1 TAB2

....

.

.

.

.

....

Page 17: 효율적인Sql작성방법 2주차

전체범위 VS 부분범위

INDEX SCAN

FULL SCAN

Page 18: 효율적인Sql작성방법 2주차

SORT 를 대신하는 INDEX 실습회원 정보를 이름 + 생년월일 순으로 descending 정렬해서 모든 데이터를 가져 오시오 .

추가되어야 할 인덱스를 정의 하시고 SQL 문을 작성하세요 .단 , ORDER BY 를 사용하지 말고 INDEX 를 활용해서 하세요인덱스 명 : 회원 _PK ( 회원 ID)

SELECT * FROM 회원

Page 19: 효율적인Sql작성방법 2주차

부분범위 처리 예제 SORT 를 대신하는 INDEX

SELECT * FROM PRODUCT WHERE YMD = ‘130321' AND ITEM LIKE 'AB%' ORDER BY YMD, ITEM

운반단위전체스캔

IN-DEX(YMD)

TABLE

SORT

.

.

.

.

.

.

.

.

SELECT * FROM PRODUCT WHERE YMD = ‘130321' AND ITEM LIKE 'AB%'

운반단위

부분스캔

INDEX (YMD+ITEM)

TABLE

Page 20: 효율적인Sql작성방법 2주차

부분범위 처리 예제INDEX 만 읽고 처리

SELECT DEPT, SUM(QTY) FROM PRODUCT WHERE DEPT LIKE '12%' GROUP BY DEPT;

운반단위

INDEX (DEPT)

TABLE

• •

GROUP BY• •

SELECT DEPT, SUM(QTY). FROM PRODUCT WHERE DEPT LIKE '12%' GROUP BY DEPT;

운반단위

INDEX (DEPT+QTY)

GROUP BY

• • • •

Page 21: 효율적인Sql작성방법 2주차

부분범위 처리 예제 INDEX 만 읽고 처리 ( 예제 )

INDEX 정보 TF_ORD_I3 (ITEM, STATUS)

SQL> SELECT STATUS, COUNT(*) FROM TF_ORDER WHERE ITEM LIKE 'HJ%' GROUP BY STATUS

20 SORT GROUP BY36631 INDEX RANGE SCAN TF_ORD_I3

2.5 sec 20 SORT GROUP BY 36630 TABLE ACCESS BY ROWID TF_ORDER 36631 INDEX RANGE SCAN TF_ORD_I3

SQL> SELECT TYPE, COUNT(*) FROM TF_ORDER WHERE ITEM LIKE 'HJ%' GROUP BY TYPE

10.3 sec

Page 22: 효율적인Sql작성방법 2주차

부분범위 처리 예제MAX 처리

SELECT MAX(SEQ) + 1 FROM PRODUCT WHERE DEPT = '12300';

운반단위

INDEX (DEPT)

TABLE

• •

SORT

• • MAX(SEQ)+1

SELECT /*+ INDEX_DESC( A INDEX1) */ SEQ + 1 FROM PRODUCT A WHERE DEPT = '12300' AND ROWNUM = 1;

운반단위

INDEX (DEPT+SEQ)

SEQ + 1

Page 23: 효율적인Sql작성방법 2주차

부분범위 처리 예제ROWNUM 의 활용

SELECT COUNT(*) INTO :CNT FROM ITEM_TABWHERE DEPT = '101' AND SEQ > 100. . . . . . . IF CNT > 0 . . .. . . . . . .

INDEX(DEPT)

TABLE

..... .....

운반단위

COUNT

SELECT 1 INTO :CNT FROM ITEM_TAB WHERE DEPT = '101' AND SEQ > 100 AND ROWNUM = 1. . . . . . . .IF CNT > 0. . . . . . . .

INDEX(DEPT)

TABLE

운반단위

X

O

Page 24: 효율적인Sql작성방법 2주차

핵심 포인트 !

집합적사고

Opti-mizer

부분범위처리

3 가지를 꼭 기억하세요 !

Page 25: 효율적인Sql작성방법 2주차

2 주차 강의

Page 26: 효율적인Sql작성방법 2주차

다양한 인덱스 스캔 방식

Page 27: 효율적인Sql작성방법 2주차

INDEX 를 사용 못하게 되는 경우와 사례

INDEX COLUMN 의 변형 SELECT * FROM DEPT

WHERE SUBSTR(DNAME,1,3) = 'ABC'

NOT Operator

NULL, NOT NULL

Optimizer 의 취사선택

SELECT * FROM EMP

WHERE JOB <> 'SALES'

SELECT * FROM EMP

WHERE ENAME IS NOT NULL

SELECT * FROM EMP

WHERE JOB LIKE 'AB%' AND EMPNO = '7890'

Function Based Index 사용시는 예외

Page 28: 효율적인Sql작성방법 2주차

다양한 인덱스 스캔 방식

어떤 골프채로 쳐야 할까요 ?=

어떤 인덱스 스캔 방식을 써야 효율적일까요 ?

Page 29: 효율적인Sql작성방법 2주차

다양한 인덱스 스캔 방식

Page 30: 효율적인Sql작성방법 2주차

INDEX UNIQUE SCAN

Unique Scan

=인덱스의 모든 컬럼 매칭 한 건

Equal 데이터 한 건 추출범위검색 조건 (between, 부등호 , like) 인 경우 Range Scan 으로 검색 ( 한 건 이상 이기 때문 )

(Unique Index 생성 시 )

Page 31: 효율적인Sql작성방법 2주차

INDEX Range Scan / Descending

INDEX UNIQE SCAN INDEX RANGE SCAN

CREATE UNIQUE INDEX 인덱스명 CREATE INDEX 인덱스명

Unique Scan Range Scan

Page 32: 효율적인Sql작성방법 2주차

INDEX Range Scan / Descending

INDEX UNIQE SCAN INDEX RANGE SCAN>데이터 추출 시 인덱스 컬럼 순으로 정렬ORDER BY , MIN, MAX 값을 대체 가능

선두 컬럼이 조건절에 사용 되지 않으면 INDEX FULL SCAN 발생

인덱스를 스캔하는 범위를 얼마만큼 줄이고테이블 엑세스를 적게 하는게 속도향상 포인트

Range ScanDescending

Page 33: 효율적인Sql작성방법 2주차

INDEX SKIP SCAN

인덱스 : 기준일자 + 업종코드 SELECT /*+INDEX(A 일별업종별거래 _IDX)*/ 기준일자 , 업종코드 , 체결건수 , 체결수량 , 거래대금 FROM 일별업종별거래 AWHERE 기준일자 BETWEEN ‘20130701’ AND ‘20130709’ AND 업종코드 = ‘01’

INDEX RANGE SCAN

SELECT /*+INDEX(A 일별업종별거래 _IDX)*/ 기준일자 , 업종코드 , 체결건수 , 체결수량 , 거래대금 FROM 일별업종별거래 AWHERE 업종코드 = ’01’

INDEX SKIP SCAN

버퍼 Pinning

Oracle 9i 부터 사용가능

중복된 값이 많을 수록 유리

Page 34: 효율적인Sql작성방법 2주차

INDEX FULL SCAN

Full Scan

INDEX UNIQE SCAN

INDEX RANGE SCAN> > INDEX SKIP

SCAN > TABLE FULL SCAN > INDEX FULL

SCAN

<?>TABLE FULL SCAN INDEX FULL SCAN ( 효율 ?)

SELECT * FROM EMP WHERE SAL > 5000 ORDER BY EMP_NAME

데이터 건이 많으면 Random Access 발생으로 TABLE FULL SCAN 을 이용 해야 효율적데이터 량이 많아지면 I/O 낭비가 심해짐데이터 건이 극히 일부일 때만 TABLE FULL SCAN 보다 유리함 .

INDEX 와 마찬가지로 ORDER BY 사용 가능

대부분 인덱스가 차지하는 면적이 테이블보다 작음

Page 35: 효율적인Sql작성방법 2주차

INDEX FAST FULL SCAN

Page 36: 효율적인Sql작성방법 2주차

INDEX FAST FULL SCAN

Index Full Scan 방식 : 1 번 브랜치 > 1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10Index Fast Full Scan 방식 : 1 >2>10>3>9>8>7>4>5>6 순서대로 전체를 읽음

Page 37: 효율적인Sql작성방법 2주차

INDEX FAST FULL SCAN

INDEX FULL SCAN INDEX FAST FULL SCAN1. 인덱스 구조를 따라 스캔 1. 세그먼트 전체를 스캔2. 결과집합 순서 보장 2. 결과집합 순서 보장 안 됨3.Single Block I/O 3.Multiblock I/O( 세그먼트 전체스캔 )4. 병렬스캔 불가 ( 파티션 돼 있지 않다면 ) 4. 병렬스캔 가능5. 인덱스에 포함되지 않은 컬럼 조회시에도 사용가능 5. 인덱스에 포함된 컬럼으로만 조회할 때 사용 가능

SELECT * FROM 공급업체 WHERE 업체명 LIKE ‘% 네트웍스 %’

SELECT /*+ORDERED USE_NL(B) NO_MERGE(B) ROWID(B)*/ B.* FROM ( SELECT /*+INDEX_FFS( 공급업체 공급업체 _IDX)*/ ROWID AS RID FROM 공급업체 WHERE INSTR( 업체명 ,’ 네트웍스’ ) > 0 )A, 공급업체 B WHERE B.ROWID = A.RID

Direct Path Read

10g 부터는 index range or full scan 일 때도 Multiblock I/O 스캔발생 ( 인덱스만 읽을 때 )

Page 38: 효율적인Sql작성방법 2주차

INDEX MERGEINDEX MERGE 와 결합 INDEX 비교

INDEX (COL1)

COL1 rowid

COL2 rowid. . . . . . 100 29 105 10 123 7123 9123 32123 35123 46123 52123 56123 65123 67123 68123 75. . . . . .

ABC 10ABC 15ABC 26ABC 28ABC 32ABC 67BCA 12BCA 27BCA 56BCA 85CBA 35CBA 46CBA 64CBA 99. . . . . . .

INDEX (COL2)

ABC 55 10ABC 67 15ABC 89 26ABC 100 29ABC 123 32ABC 123 67ABC 180 76BCA 100 12BCA 100 27BCA 123 56BCA 123 85CBA 85 35CBA 123 46CBA 214 64. . . . . . . . .

COL1 COL2 rowid

INDEX (COL1 + COL2)

결합 INDEXINDEX MERGE

Page 39: 효율적인Sql작성방법 2주차

AND-EQUAL

SELECT CUSTNO, CHULDATE FROM CHULGOT WHERE CUSTNO = 'DN02' AND STATUS = '90'

SELECT CUSTNO, CHULDATE FROM CHULGOT WHERE CUSTNO LIKE 'DN%' AND RTRIM(STATUS) LIKE '9%'

TABLE ACCESS BY ROWID CHULGOT AND-EQUAL INDEX RANGE SCAN CH_STATUS INDEX RANGE SCAN CH_CUSTNO

SELECT CUSTNO, CHULDATE FROM CHULGOT WHERE CUSTNO LIKE 'DN%' AND STATUS LIKE '9%'

Oracle 10g 부터 폐기된 기능입니다 ! 10g 이하버젼을 쓰시는 분만 참고하세요 .

Page 40: 효율적인Sql작성방법 2주차

RANDOM ACCESS

운반단위

INDEX (FLD)

.....

2

차가공

TAB TAB

운반단위

oxo

oox

o

x

.....

x

x

2

차가공

oo

Index Range Scan Full Table Scan

RANDOM ACCESS 가 많이 발생되면 I/O 효율이 떨어집니다 .

Page 41: 효율적인Sql작성방법 2주차

BITMAP

SELECT count(*) FROM parts WHERE size = 'MED' AND color = 'RED'

Index on COLORcolor = 'BLUE' 0 0 0 1 0 0 1 0 1 0 1 0 0 0 1 0color = 'RED' 0 1 1 0 1 0 0 1 0 0 0 0 1 0 0 1color = 'GREEN' 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 0

Index on SIZE

size = 'SMALL' 0 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1size = 'MED' 1 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0size = 'LARGE' 0 0 0 1 0 0 0 0 1 0 1 0 1 0 1 0

010

010

PARTStable 001 GREEN MED 98.1

002 RED MED 1241003 RED SMALL100.1004 BLUE LARGE 54.9005 RED MED124.1006 GREEN SMALL 60.1 ... .... ..... ...

partno color size weight

010

010

Page 42: 효율적인Sql작성방법 2주차

BITMAP

상품 ID 상품명 색상1 AAA GREEN2 BBB GREEN3 CCC RED4 DDD BLUE5 EEE RED6 FFF GREEN7 GGG BLUE8 HHH  9 JJJ RED

BLUE GREEN RED NULL0 1 0 00 1 0 00 0 1 01 0 0 00 0 1 00 1 0 01 0 0 00 0 0 10 0 1 0

테이블 저장 데이터

Page 43: 효율적인Sql작성방법 2주차

BITMAP

B*Tree INDEX

Page 44: 효율적인Sql작성방법 2주차

BITMAP

BITMAP INDEX

Page 45: 효율적인Sql작성방법 2주차

BITMAP

BITMAP INDEX

레코드 찾아가는 방법Block 안에 저장할 수 있는 최대 Record 개수 730 개테이블에 20 개 BLOCK 이 할당이 되어있다고 가정

730 X 20 = 14600 9500 번째가 1 라면 BLOCK 위치 : 9500 / 730 = 13

Record 위치 : MOD(9500 / 730) = 10

Page 46: 효율적인Sql작성방법 2주차

마무리

INDEX RANGE SCAN

INDEX SKIP SCAN

INDEX FAST FULL SCAN

IND

EX UN

IQU

E SCAN

FULL SCAN

Page 47: 효율적인Sql작성방법 2주차

마무리