48
본본본 본본 본본본 본본본 본본본본본 . IT 본본본본 본본 본본본본 SQL 본본본본 3 본본 본본본본본 3 본 본본본

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

  • Upload
    -

  • View
    584

  • Download
    5

Embed Size (px)

Citation preview

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

본서의 모든 이미지 출처는 생략합니다 .

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

시스템개발 3 팀 강희동

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

1~2 주차 Review

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

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

효율적인SQL작성방법

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

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

효율적인SQL작성방법

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

전체범위 VS 부분범위

전 체 범 위 처 리

2차가공

운반단위

• • • •

1차스캔

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

부 분 범 위 처 리

2차가공

운반단위

1차스캔

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

효율적인SQL작성방법

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

전체범위 VS 부분범위

INDEX SCAN

FULL SCAN

효율적인SQL작성방법

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

다양한 인덱스 스캔 방식

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

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 사용시는 예외

효율적인SQL작성방법

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

INDEX Range Scan / Descending

INDEX UNIQE SCAN INDEX RANGE SCAN>데이터 추출 시 인덱스 컬럼 순으로 정렬ORDER BY , MIN, MAX 값을 대체 가능선두 컬럼이 조건절에 사용 되지 않으면 INDEX FULL SCAN 발생인덱스를 스캔하는 범위를 얼마만큼 줄이고테이블 엑세스를 적게 하는게 속도향상 포인트

Range ScanDescending

효율적인SQL작성방법

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

INDEX UNIQUE SCAN

Unique Scan

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

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

(Unique Index 생성 시 )

효율적인SQL작성방법

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

INDEX SKIP SCAN

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

INDEX RANGE SCAN

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

INDEX SKIP SCAN

버퍼 Pinning

효율적인SQL작성방법

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

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 보다 유리함 .

데이터 저장공간 : 컬럼길이 X 레코드 수INDEX 와 마찬가지로 ORDER BY 사용 가능

효율적인SQL작성방법

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

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

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

효율적인SQL작성방법

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

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

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

효율적인SQL작성방법

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

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 이하버젼을 쓰시는 분만 참고하세요 .

효율적인SQL작성방법

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

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 효율이 떨어집니다 .

효율적인SQL작성방법

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

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 18: 효율적인Sql작성방법 3주차

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 19: 효율적인Sql작성방법 3주차

BITMAP

주의 !!중복되는 값의 수가 적으면 BITMAP INDEX??????NO!!!!저장 시에 속도도 빠르고 용량도 적게 차지하지만 ( 물론 인덱스 블록을 읽는 범위가 작아서 아주 살짝 빠르긴 함 ) 조회 속도는 B*Tree 인덱스와 다른게 없음 ..(Random 액세스 )

이런 경우 사용하세요1. Null 에 대한 검색이 필요한 경우2. 하나의 컬럼 이상 조건을 걸 경우 SELECT * FROM 상품

WHERE ( 크기 =‘SMALL’ OR 크기 IS NULL) AND 색상 = ‘GREEN’

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

BITMAP

단점 !!!레코드 하나만 변경 되더라도 비트맵 범위에 속한 모든 레코드에 LOCK 발생 !!!

OLTP 환경에서 비트맵 인덱스 적용이 어려운 이유… .

인덱스 컬럼에 변경이 없는 곳에 사용해야 안전합니다 !

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

3 주차

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

INDEX 의 중요성 !

테이블 드라이빙 우선순위부서 테이블 (100 건 )

부서번호 (PK)사원 테이블 (10 만건 )

사원번호 (PK)

부서번호 (FK)

조건 - 부서테이블 , 사원테이블에는 PK 인덱스만 존재- 전체 데이터 검색문제1 번 테이블이 먼저 드라이빙 하는게 유리할까요 ?2 번 테이블이 먼저 드라이빙 하는게 유리할까요 ?

-1 번 테이블이 먼저 드라이빙 될 경우부서 테이블을 100 건을 스캔하고서 사원 테이블을 10 만번 스캔100 X 100,000 = 1,000,000 ( 천만번 스캔 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)

-2 번 테이블이 먼저 드라이빙 될 경우사원테이블을 10 만번 스캔하고서 부서 테이블을 스캔하는데 부서번호키가 Unique index 이기 때문에 1 번만 읽고 스캔100,000 X 1 = 100,000 ( 십만번 스캔 )

효율적인SQL작성방법

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

INDEX 의 중요성 !

INDEX 처리 원리

SORT 된 결과

TABLE (EMP)

EMPNO ENAME JOB7654 강감찬 부장7900 류관순 과장 7689 황진이 과장

7499 이순신 차장

7934 변강쇠 부장

7844 조자룡 차장

7369 안중근 이사

7839 장보고 과장

7531 신윤복 차장

7856 홍길동 과장

7432 김유신 부장

7827 김두환 부장

INDEX (JOB)

INDEX-KEY ROWID과장 0000A95B.0002.0001

과장 0000A95B.0005.0001

과장 0000E62E.0009.0001

과장 0000E9BE.0002.0001

부장 000062BE.0001.0001

부장 000062BE.0003.0001

부장 000093A6.0005.0001

부장 000093B2.000B.0001

이사 000069C5.0001.0001

차장 0000E9BE.0002.0001

차장 0000E9BE.0005.0001

차장 0000E9BE.000B.0001

SELECT empno, ename, job FROM EMPWHERE JOB IN (' 부장‘ ,'이사‘ )

효율적인SQL작성방법

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

아 ~ 몰라 귀찮아 대충 쓸래

우리가 사용하는 INDEX 는 효율적일까 ?

지금도 충분히 빨라 잘 만들었어 ~ 움 ~

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

INDEX 손익분기점

가정전체 10,000 row1 block 당 평균 10 row전체 1,000 block

효율적인SQL작성방법

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

INDEX 손익분기점

가정전체 10,000 row1 block 당 평균 10 row전체 1,000 block

운반단위

INDEX (FLD)

.....

2

차가공

TAB TAB

운반단위

oxo

oox

o

x

.....

x

x

2

차가공

oo

Index Range Scan Full Table Scan

1,000 row read 를 위해 1,000 block access 낮은 Hit Ratio

10,000 row read 를 위해 1,000 block access 높은 Hit Ratio

인덱스 사용여부 고려사항Scan 범위Hit RatioClustering Factor

손익분기점(10 ~15%)

효율적인SQL작성방법

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

INDEX 손익분기점 효율적인SQL작성방법

Hit Ratio 를 올리기 위한 기법IOT(Index-Oraganized Table)

Create table 테이블명 ( 컬럼명 타입 primary key, …….)organization heap

Create table 테이블명 ( 컬럼명 타입 primary key, …….)organization index

파티셔닝

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

INDEX 손익분기점 효율적인SQL작성방법

Hit Ratio 를 올리기 위한 기법클러스터 테이블

인덱스 클러스터 테이블

IOT 와 비슷…… 차이점1. 정렬상태 2. PK 가 아니여도 생성이 가능 함 .

해시 클러스터 테이블- 해싱 알고리즘을 이용해 클러스터 키값을 데이터 블록주소로 변환- ‘=‘ 검색만 사용 가능

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

INDEX 손익분기점

NULL 을 활용한 튜닝 기법

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

INDEX SCAN, FULL SCAN SWITCH

NULL- NULL =NULL + 10 =NULL

SELECT * FROM 테이블WHERE NVL( 컬럼 ,’N’) = ‘Y’

SELECT NVL( 컬럼 ,’Y’)

FROM 테이블WHERE NVL( 컬럼 ,’N’) = ‘Y’

SELECT * FROM 테이블WHERE NVL( 컬럼 ,1) > 1

SELECT * FROM 테이블 A, 테이블 BWHERE NVL(A. 컬럼 ,’C’) = NVL( 컬럼 ,’C’)

효율적인SQL작성방법

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

INDEX SCAN, FULL SCAN SWITCH

확정된 없다

아직 미확정혼돈 NULL

공포증

확실한 DEFAULT 처리

TABLE PROGRAM

DATA 소실우려어떤 값보다 크지도 않고 작지도 않다 .

NULL 을 포함한 조건문 IN (‘1’,’2’,NULL)?

NULL 과의 연산결과는 NULL

NULL 은 언제 사용 해야 하나 ?

효율적인SQL작성방법

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

INDEX SCAN, FULL SCAN SWITCH

NULL 이럴 때만 사용 합시다 !- 미 확정 값을 표현하고자 할 때- 결합인덱스의 구성 컬럼이 된다면 NOT NULL!- 인덱스 조건 값으로 자주 사용 된다면 NOT NULL!

특정 값이 지나치게 많고 나머지 값만 주로 인덱스로 액세스A 사B 사C 사D 사E 사F 사

B

컬럼 값

CDEF

NULL TABLE FULL SCAN

INDEX RANGE SCAN

효율적인SQL작성방법

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

INDEX SCAN, FULL SCAN SWITCH

(78%)

4% 6% 7%5%

A

BC DE

COL1 분포도

KEYCOL1. . . .

TABLE1(10000 row) CREATE INDEX index_name

ON table_name (COL1);

COL1 = 'A' 를 그대로

COL1KEY . . . .

A. . . . . . . .

A. . . . . . . .

A. . . . . . . .

B. . . . . . . .

B. . . . . . . .

. . . .. . . . . . . .

COL1 ROWID

A . . . .

A . . . .

A . . . .

B . . . .

B . . . .

. . . . . . . .

TABLE1(10000 row)

INDEX1(10000 row)

COL1 = 'A' 를 COL1 NULL 로

COL1KEY . . . .

Null. . . . . . . .

Null. . . . . . . .

Null. . . . . . . .

B. . . . . . . .

B. . . . . . . .

. . . .. . . . . . . .

COL1 ROWID

B . . . .

. . . . . . . .

C . . . .

. . . . . . . .

TABLE1(10000 row)

INDEX1(2000 row)

효율적인SQL작성방법

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

INDEX SCAN, FULL SCAN SWITCH 효율적인 SQL 작성방법

좌변 가공하지마

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

INDEX 컬럼의 변형

SELECT * FROM EMP WHERE SUBSTR(DNAME,1,3) = 'ABC'

SELECT * FROM EMP WHERE DNAME LIKE 'ABC%'

SELECT * FROM EMPWHERE SAL * 12 = 12000000

SELECT * FROM EMPWHERE TO_CHAR(HIREDATE,'YYMMDD') = ‘130712'

SELECT * FROM EMP WHERE HIREDATE = TO_DATE(‘130712','YYMMDD')

SELECT * FROM EMP WHERE SAL = 12000000 / 12

SELECT * FROM EMPWHERE DEPTNO || JOB = '10SALESMAN'

SELECT * FROM EMPWHERE DEPTNO = '10' AND JOB = 'SALSMAN'

효율적인SQL작성방법

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

INDEX 컬럼의 변형

SELECT * FROM EMPWHERE NVL(COMM,0) < 100

?

SELECT * FROM EMPWHERE COMM < 100

SELECT * FROM EMP WHERE EMPNO BETWEEN 100 AND 200 AND NVL(JOB,'X') = 'CLERK'

SELECT * FROM EMP WHERE EMPNO BETWEEN 100 AND 200 AND JOB = 'CLERK'

컬럼 값에 NULL 이 존재하는 경우

해결방안 : NULL 값 0 으로 변경

효율적인SQL작성방법

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

INDEX 컬럼의 변형

SELECT * FROM EMPWHERE JOB = 'MANAGER'

SELECT * FROM EMPWHERE RTRIM(JOB) = 'MANAGER'

SELECT * FROM EMPWHERE EMPNO = 8978

SELECT * FROM EMP WHERE RTRIM(EMPNO) = 8978

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

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

의도적인 SUPPRESSING

효율적인SQL작성방법

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

INDEX 컬럼의 변형

의도적인 SUPPRESSINGSELECT X.CUSTNO, CHULDATE, CUSTNAME FROM MECHUL1T X, MECHUL2T Y WHERE X.SALENO = Y.SALENO AND X.SALEDEPT = '710' AND Y.SALEDATE LIKE ‘1301%' 10 Sec

SELECT X.CUSTNO, CHULDATE, CUSTNAME FROM MECHUL1T X, MECHUL2T Y WHERE X.SALENO = Y.SALENO AND RTRIM(X.SALEDEPT) = '710' AND Y.SALEDATE LIKE ‘1301%' 1 Sec

SELECT X.ORDNO, ORDDATE, ITEM FROM ORDER1T X, ORDER2T Y WHERE X.ORDNO = Y.ORDNO AND X.ORDDATE LIKE ‘1301%' AND Y.ORDDEPT = '710' ORDER BY ORDDATE 13 Sec

SELECT X.ORDNO, ORDDATE, ITEM FROM ORDER1T X, ORDER2T Y WHERE RTRIM(X.ORDNO) = Y.ORDNO AND X.ORDDATE LIKE ‘1301%' AND Y.ORDDEPT = '710’ 1 Sec

연결고리 확인 ! 인덱스가 없으면 없는 쪽부터 드라이빙 !!( 중요 !)

효율적인SQL작성방법

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

INDEX 컬럼의 변형

SELECT * FROM SAMPLET WHERE NUM LIKE '9410%'

CREATE TABLE SAMPLET ( CHR VARCHAR2(10), NUM NUMBER (12,3), VAR VARCHAR2(20), DAT DATE)

SELECT * FROM SAMPLET WHERE CHA = 10

SELECT * FROM SAMPLET WHERE TO_NUMBER(CHA) = 10

SELECT * FROM SAMPLET WHERE TO_CHAR(NUM) LIKE '9410%'

SELECT * FROM SAMPLET WHERE DAT = '01-JAN-94'

SELECT * FROM SAMPLET WHERE DAT = TO_DATE('01-JAN-94')

DATA TYPE 의 변형효율적인SQL작성방법

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

INDEX 컬럼의 변형

DATA TYPE 의 변형 TABLE ACCESS FULL CHULGOT

1 row, 28.5 sec

SQL> SELECT SUM(UNCOST) FROM CHULGOT WHERE STATUS = 90

SORT AGGREGATE TABLE ACCESS BY ROWID CHULGOT INDEX RANGE SCAN CH_STATUS 1 row,

0.15 sec

SQL> SELECT SUM(UNCOST) FROM CHULGOT WHERE STATUS = '90'

SQL> SELECT CHULNO, CUSTNO, UNCOST FROM CHULGOT WHERE CFMDEPT LIKE '71%'

NESTED LOOPS TABLE ACCESS FULL ORDER1T TABLE ACCESS BY ROWID CHULGOT INDEX RANGE SCAN CH_CFMDEPT

rows,71 sec

SQL> SELECT ORDNO, CHULNO, STATUS FROM ORDER1T X, CHULGOT Y WHERE X.CUSTNO = Y.CUSTNO AND X.ORDDEPT = Y.CFMDEPT AND y.CHULDATE LIKE ‘1307%'

NUMBER type

TABLE ACCESS FULL CHULGOT

rows, 30 sec

NUMBER > (CHAR or VARCHAR)

효율적인SQL작성방법

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

INDEX 활용기준

INDEX 적용기준6 블럭 이상의 테이블에 적용 (6 블럭 이하는 연결고리만 )

컬럼의 분포도가 10~15% 이내인 경우 적용

분포도가 범위 이내더라도 절대량이 많은 경우에는 클러스터링 검토

분포도가 범위 이상이더라도 부분범위처리를 목적인 경우 적용

인덱스만 사용하여 해결하고자 하는 경우 분포도가 나쁘더라도 적용 가능

효율적인SQL작성방법

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

INDEX 활용기준

INDEX 선정기준효율적인SQL작성방법

분포도가 좋은 컬럼은 단독적으로 생성하여 활용도 향상 자주 조합되어 사용되는 경우는 결합인덱스 생성 각종 엑세스 경우의 수를 만족하도록 인덱스 간의 역할 분담 가능한 수정이 빈번하지 않은 컬럼 기본키 및 외부키 ( 조인의 연결고리가 되는 컬럼 )

결합 인덱스의 컬럼 순서 선정에 주의

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

INDEX 활용기준INDEX 선정절차

효율적인SQL작성방법

• 해당 테이블 사용하는 모든 쿼리의 액세스 유형 조사1. 해당 테이블의 액세스 유형조사

• 인덱스 후보로 어떤 컬럼이 좋을지 선정하고 각 컬럼에 데이터 분포도 분석2. 대상 컬럼의 선정 및 분포도 분석

• FOR 문 안에서 실행되는 쿼리 일 경우 최적에 액세스 경로를 탈 수 있게 최적화3. 반복 수행되는 액세스 경로의 해결

• 데이터량이 많은 경우 검토 (초기에는 적용하기 쉬우나 운영 중에는 초기에 비해 적용이 어려움 )4. 클러스터링 검토

• 컬럼의 순서를 결정5. 인덱스 컬럼의 조합 및 순서의 결정

• 잘못된 쿼리로 인해 인덱스 적용이 안 될 수 있음 . 이런 쿼리들을 최적화 쿼리로 수정• 모든 작업이 완료되면 일괄 적용6. 시험생성 및 테스트 그리고 일괄 수정

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

INDEX 활용기준결합 INDEX 순서 절차

효율적인SQL작성방법

항상 사용하는가 ?

항상 EQUAL 로 사용되는가 ?

분포도가 좋은 컬럼 우선

SORT 순서는 ?

어떤 컬럼을 추가 ?(후보선수 )

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

추가된 인덱스가 미치는 영향 효율적인SQL작성방법

SELECT * FROM TAB1 WHERE A = '10' AND B = ‘130415' AND C = '123'

AB CINDEX1 IN-DEX2

A = '10‘B = ‘130415'

C = '123'

(INDEX1 사용 )

D column 추가

ABD CINDEX1 IN-DEX2

C = '123'(INDEX2 사용 )

A = '10‘B = ‘130415‘D LIKE ‘A%’

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

추가된 인덱스가 미치는 영향 효율적인SQL작성방법

예제CHULITEM table Primary Key : CHULNO + ORDNO + ITEM

SQL> SELECT CHULNO, ORDNO, ITEM, CHULQTY FROM CHULITEM WHERE CHULNO = '2565' AND ORDNO = '8584' AND LOT = 'P0009'

1 rows, 0.01sec

TABLE ACCESS BY ROWID CHULITEM INDEX RANGE SCAN PK_CHULITEM

SQL> SELECT CHULNO, ORDNO, ITEM, CHULQTY FROM CHULITEM WHERE CHULNO = '2565' AND ORDNO = '8584' AND LOT = 'P0009'

1 rows, 37.7sec

SQL> CREATE INDEX CI_LOT ON CHULITEM (LOT)

TABLE ACCESS BY ROWID CHULITEM INDEX RANGE SCAN CI_LOT

SQL> SELECT CHULNO, ORDNO, ITEM, CHULQTY FROM CHULITEM WHERE CHULNO = '2565' AND ORDNO = '8584' AND LOT = 'P0009'

1 rows,0.01 sec

SQL> CREATE INDEX CI_LOT_ITEM ON CHUITEM (LOT,ITEM)

TABLE ACCESS BY ROWID CHULITEM INDEX RANGE SCAN PK_CHULITEM

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

마무리

SQL 에서 완벽이란 없습니다 .

데이터 분포도 , 흐름 , 패턴에 맞는 최적의 쿼리 작성

효율적인SQL작성방법

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

마무리

기대치요구사항

사용자가 어떻게 사용 할 것인가 ?

효율적인SQL작성방법