<도서정리> 친절한 sql 튜닝 1

  • 1. SQL 처리 과정과 I/O

옵티마이저 – SQL 최적화 기능, 효율적인 액세스 경로 선택, 옵티마이저 힌트, 실행계획

 

SGA(시스템 글로벌 애리아) – 서버 프로세스와 백그라운드 프로세스가 공통으로 사용하는 메모리

(DB 버퍼캐시, 리두 로그 버퍼, 라이브러리 캐시 등이 포함되어 있음)

Ø  라이브러리 캐시 (코드 캐시; sql 함수 프로시저 실행계획 등)

소프트 파싱 캐시에서 해결되는 파싱; 라이브러리 캐시의 특장점

하드 파싱 - 하드디스크까지 가서 최적화와 로우소스까지 생성해야 하는 파싱

Ø  DB 버퍼캐시 (데이터 캐시; 디스크에서 읽은 데이터 블록)

I/O call 줄임

 

I/O 튜닝

프로세스는 준비-실행-대기 상태를 반복하기 때문에 디스크 I/O call이 발생하면 그 동안 프로세스는 대기 상태가 됨.

, 디스크 I/OSQL 성능을 좌지우지함

블록 : DBMS가 데이터를 읽고 쓰는 단위 (레코드 하나가 아닌 레코드 속한 블록을 통째로 읽음)

시퀀셜 액세스 : 순차적 액세스, full table scan, 다중 블록 I/O

랜덤 액세스 : 랜덤으로 한 블록씩 접근; 인덱스는 single block I/O

 

Sql 튜닝을 통해 읽어들이는 총 블록 개수를 감소시켜야 함

실제 성능을 향상시키려면 건들일 수 없는 물리적 I/O가 아닌 통제 가능한 논리적 I/O를 감소시켜야 함

 

Table Full Scan (대량 데이터 호출) VS Index Range Scan (소량 데이터 호출; ROWID 제공)


  • 2. 인덱스

1. 인덱스 스캔 효율화 튜닝

2. 랜덤 액세스 최소화 튜닝 ☆

 

선두 컬럼 가공되지 않 상태 조건절에 있어야한다!!

시작점을 찾아야 일부만을 스캔하기 때문이다.

 

인덱스는 데이터가 정렬되어 있기 때문에 range scan 할 수 있다. , 소트 연산 생략 효과가 있다.

-       인덱스 구성대로 order by col1, col2하면 소트 연산 생략되지만

order by col1 || col2하면 생략 안됨

-       테이블 alias 사용 시에는 order by alias.col로 해야함

-       (자동)형변환도 가공으로 취급됨 - null값도 처리해주기

 

인덱스 full scan도 인덱스 컬럼 순으로 정렬됨 >> 이것은 소트 연산 생략 의도로 사용하기도 함

힌트 first_rows를 사용하면 거의 모든 범위의 테이블 액세스가 일어나 성능 면으로 좋지 않지만
부분범위 처리 시에는 소트 연산을 생략함으로써 일부를 빠르게 출력할 수 있음

(table full scan, index range scan 이외에도 index unique scan, index skip scan, index fast full scan, index range scan descending 있음)

 

  • 3. 인덱스 튜닝

Rowid는 논리적 주소이며 포인터가 아니다.
버퍼 캐시에서 DBA(데이터파일번호+블록번호)를 통해 테이블 블록을 찾는 구조이다. (고비용 구조)

인덱스 클러스터링 팩터 

특정 컬럼을 기준으로 같은 값을 갖는 데이터가 서로 모여있는 정도
이것이 안 좋은 인덱스를 사용하면 그만큼 블록 I/O가 발생

인덱스 손익분기점

index range scan에 의한 테이블 액세스가 table full scan보다 느려지는 지점
이것이 CF클러스터링 팩터와 관련이 있음

테이블 파티셔닝(ex) date 기준) -> full scan을 빠르게 처리할 수 있음

인덱스 컬럼 추가

인덱스에 컬럼을 추가하는 것만으로도 성능 향상.
하지만 추가해야할 컬럼은 많아지고, 인덱스가 많을수록 정렬 때문에 성능에 안 좋음

Include 인덱스

컬럼에 추가하는 것이 아닌 index 생성 시 끝에 include(column)하면 됨
그러면 기존 방식으로 추가한 컬럼은 수직적 탐색에 사용하고
include로 추가한 컬럼은 리프 블록에만 저장하여 수평적 탐색에 필터 조건으로 사용 가능

클러스터형 인덱스

테이블을 인덱스 구조로 형성
인덱스 리프 블록이 곧 데이터 블록
Create table index_ (col1 number, col2 varchar(10),
Constraint index_pk primary key(a) )
Organization index;

클러스터 테이블

같은 공간에 저장해 둘 뿐, 위와 같이 정렬하지 않음
랜덤 액세스가 적고, 클러스터에 도달하면 시퀀셜 방식으로 스캔

-       인덱스 클러스터

Create cluster c_dept ( eptno number(2) ) index;
Create index c_dept on cluster c_dept;
Create table dept ( deptno number(2) not null
, dname varchar2(14) not null
, loc varchar2(13) )
Cluster c_dept( deptno );

-       해시 클러스터

Create cluster c_dept ( eptno number(2) ) hashkeys 4;
Create table dept ( ... );

 

부분범위 처리 활용

아무리 데이터가 많아도 빠른 응답속도

           큰 사이즈로 데이터 호출하여 fatch call 최소화

 

인덱스 스캔 효율화

액세스 조건(스캔 범위 결정)필터 조건(테이블 액세스 결정)

   선행 컬럼들이 모두 = 조건이면 조건이 모두 모여있어 인덱스 스캔 범위가 됨

   In-List 유용 > In list iterator : in 개수만큼 index range scan 반복함 good

but In-list는 원래 '필터' 조건. 본질적으로는 = 조건과 다름

                              데이터가 대용량으로 굉장히 많아야 = 조건으로 유용하다

  힌트 NUM_INDEX_KEYS(a 고객별가입상품_X1 1) 사용 : 인덱스의 첫 번째 컬럼(세 번째 인자에    명시)까지 인덱스 액세스 조건으로 사용

  소트 연산을 생략하기 위해 In-list가 액세스 조건이 아닌 필터 조건으로 풀려야할 때가 있음 ->
  이 경우에는 인덱스의 맨 끝으로 위치시키면 됨!

Between 조건을 in-list로 전환할 때는 데이터가 멀리 떨어져 있거나 데이터가 적어야 유용

Index skip scan을 사용하면(힌트 INDEX_SS) 선두컬럼을 in이 아닌 between에 사용해도  블록만을 스캔하고 효율적으로 스캔

Like보다 Between이 좋음. 하지만 범위검색 조건도 남용하면 안 좋음

OR 조건은 인덱스가 아닌 컬럼에 사용하면 됨

인덱스 선두 컬럼에 between, like 사용 금물

Union all 사용 옵션 조건 컬럼도 인덱스 액세스 조건으로 사용함 good

Null값 해결을 위해 NVL(IFNULL), DECODE 사용 (but OR expansion 한 번만 가능)

조건절의 컬럼이 모두 인덱스에 있으면 함수도 모두 액세스 조건으로 한 번만 수행됨 good

 

- 인덱스 구성 조건 : 데이터량이 많으면 적절한 인덱스 구성이 꼭 필요

           1. 선두 컬럼조건절에 반드시 사용하고,

2. 조건절에 많이 사용하고

3. = 조건으로 자주 조회하는 컬럼

4. 수행 빈도도 큰 영향

ex) 일자/일시 조건을 선두에 두고, 자주 사용하는 필터 조건을 뒤쪽에 추가

 

소트연산 생략하기 위한 인덱스 구성

= 연산자로 사용한 조건절 컬럼

ORDER BY 절에 기술한 컬럼이어야 함

            + 다른 조건절일 경우 데이터 분포 고려해서 인덱스에 추가하기

 

인덱스 생성 시 컬럼의 선택도충분히 낮은지도 살펴봐야함 <> 변별력 높은 컬럼인지 확인!

           카디널리티가 높은 컬럼(변별력이 낮음)은 테이블 액세스가 많이 발생한다

           인덱스 생성 시에는 선택도가 중요하고

           컬럼 간 순서를 결정할 때는 필수 조건 여부, 연산자 형태가 더 중요하다

 

 

댓글을 작성해보세요.

  • highlrang
    highlrang

    데이터가 분산되어있지 않을수록 인덱스의 성능이 향상된다

    • 분산도가 낮은 상태; 특정 값을 가진 데이터가 많이 고르게 있을수록 인덱스는 많은 효과를 나타내지 않지만
      복합 인덱스보다는 단일 인덱스가 효과가 있다

    • 분산도가 높은 상태; 특정 값을 가진 데이터가 치중되어 있을수록 데이터 영역을 보다 좁힐 수 있는 복합 인덱스가 효과가 있다

  • highlrang
    highlrang

    인덱스는 보통 많은 데이터 사이에서 특정 값을 가지는 데이터를 호출할 때 사용된다.

    인덱스는 ID, YN, DEPTH 등 조건절에서 많이 사용되는 컬럼에 건다.