반응형

📝SQL 튜닝

최소한의 CPU I/O 메모리를 사용해 최대한 빠른 시간내 원하는 데이터 작업을 수행시키는 것
아무리 쿼리의 성능을 튜닝해도 근본적인 스키마 구조가 문제라면 밑빠진 독에 물 붓기이기 때문에 이런 경우 아예 근본적인 스키마 구조부터 뜯어고쳐야할 수 있다.
데이터 모델링을 할 때는 일반적으로 사용자의 이용 빈도(자주 사용하는 화면)를 고려하며 설계 하는 게 좋다

📝옵티마이저

DBMS의 두뇌라고 표현할 수 있다. SQL이 들어오면 문법 에러 및SQL문을 처리하는 최적의 방법을 도출해서 실행하게 한다.

📝SQL 실행 순서

  1. 문법 오류 검사
  2. 실행한 적이 있는 SQL문인지 메모리(SHARED POOL)에서 체크 후 실행
    1. 실행한 적 있으면 기존 방식으로 실행(SOFT PARSING) → 
    2. 실행한 적 없으면 처리 방식에 대한 실행 계획 수립(HARD PARSING) 그 이후 SHARED POOL에 실행 계획 저장

 

📝옵티마이저 종류

규칙 기반 옵티마이저

  • 특정 규칙을 기반으로 실행 계획 수립하고 우선순위가 높은 걸 우선시한다.
  1. ROWID에 의한 단일행 실행
  2. 클러스터 조인에 의한 단일행 실행
  3. AHSH CLUSTER KEY에 의한 단일행 실행
  4. UNIQUE KEY 또는 PRIMARY KEY에 의한 단일행 실행
  5. 클러스터 조인
  6. HASH CLUSTER KEY
  7. INDEXED CLUSTER KEY
  8. 결합 인덱스
  9. 단일 컬럼 인덱스
  10. 인덱스에 의한 컬럼 BOUNDED RANGE
  11. 인덱스에 의한 컬럼의 UNBOUNDED RANGE
  12. SORT MERGE JOIN
  13. 인덱스로 구성된 컬럼의 MAX 또는 MIN 처리
  14. 인덱스로 구성된 컬럼의 ORDER BY
  15. FULL TABLE SCAN

예를 들어 아래와 같은 쿼리문이 존재할 때 emp_no가 PRIMARY KEY 설정(인덱스)가 안 되어있는 경우 15번의 FULL TABLE SCAN 방식으로 실행될 것이고 있는 경우4번의 방식으로 실행되게 된다.

SELET E.e_name
FROM emp E
WHERE E.emp_no = '12345';


우선 순위가 정해져있기 때문에 미리 예측을 할 수 있다는 장점이 있다. 그렇기 때문에 SQL을 통제하는 것이 가능하다

하지만 이러한 규칙이 항상 유리하지 않다
성별인 남자이고 입사일이 2013년 1월 1일 ~ 2013년 1월 3일인 사람을 검색하는 SQL을 작성하고자할 때 아래 SQL과 같이 작성하는 경우 성별인 남자인 직원을 걸러내는 인덱스를 사용하는 것보다 3일 사이에 입사한 직원을 걸러내는게 더 효율적이다. 
→ 남자인 사람에서 입사일을 걸러내는 것보다 입사일에서 남자인 사람을 걸러내는게 불필요한 데이터를 많이 읽게 되는 걸 줄일 수 있다

SELECT E.e_name
FROM emp E
WHERE E.gender = '남자'
AND E.hiredate BETWEEN '20130101' AND '20130103'


위와 같은 쿼리를 좀더 효율적으로 하기 위해 인덱스를 안 타게끔 아래와 같이 조정이 가능하긴 하다.

SELECT E.e_name
FROM emp E
WHERE E.gender || '' = '남자'
AND E.hiredate BETWEEN '20130101' AND '20130103'

 

또한 규칙기반 옵티마이저에서는 이러한 단점들이 존재한다.

  1. 힌트를 사용할 수 없다
  2. HASH JOIN을 사용 할 수 없다
  3. 거의 사용하지 않는 추세이며 ORACLE의 경우 10g 이후 공식적으로 지원하지 않는다.

비용  기반 옵티마이저

  • 최소 비용으로 처리할 수 있는 실행 계획 수립, 가장 많이 쓰이는 형식의 옵티마이저
  • 하나의 SQL을 받으면 최대 2,000개의 실행 계획을 만들고 가장 적은 비용이 드는 실행계획을 사용자에게 제시한다.


📝동작방식 (SQL → Parsing → Query Transformer → Estimator → Plan Generator)

 

 

Query Transformer

PARSING 과정을 거친 SQL은 PARSING 트리 형태로 변형되어 Query Transformer는 넘겨 받은 SQL을 보고 같은 결과를 도출하되 좀 더 나은 실행 계획을 갖는 SQL로 변형이 가능한지 판단해 변환 작업을 수행
예를 들면 복잡한 서브쿼리나 뷰를 사용한 SQL을 일반적인 조인 형태의 SQL로 변환해 실행 계획을 도출하기 좋은 상태로 만든다.

Estimator

Query Transformer를 통해 변환 작업을 마치고난 SQL은 Estimator로 넘겨지게 되는데 이때 수행하는데 드는 총 비용을 계산한다.

Plan Generator

Estimator를 통해 계산된 값들을 토대로 후보군 실행계획 도출 Row Source Generator를 통해 출력이 가능한 코드 형태로 바꾼다.

📝FIRST_ROWS_n

비용기반 옵티마이저는 CHOOSE, FIRST_ROWS와 같은 모드도 존재하지만 현재는 사용하지 않고 DBMS에서도 FIRST_ROWS_n을 권장하며 실행 결과를 출력하는데 걸리는 응답 속도를 최적화 는게 목표이다.

📝ALL_ROWS

SQL 실행 결과 전체를 빠르게 처리하는데 최적화된 실행 계획을 세우는 것입니다. ORACLE의 경우 10g 이후에 이값이 기본적으로 설정되어있다.

 

📝옵티마이저 이용 통계정보

옵티마이저의 경우 통계 정보를 따라 자동적으로 최적의 실행계획을 세운다 이용하는 통계정보는 아래와 같다

테이블 테이블 전체 행의 수
테이블이 차지하고 있는 전체 블록 수
테이블의 행들이 갖는 평균 길이 등
컬럼 컬럼 값의 종류
컬럼 내 NULL 값의 분포도
컬럼 값의 평균 길이
컬럼 내 데이터 분포의 추정치 등
인덱스  LEAF BLOCK 수 : 데이터 보관하는 블록 수
LEVELS : 인덱스 트리의 LEVELS 정보
CLUSTERING FACTOR : 접근하고자 하는 데이터가 모여 있는 밀집도
시스템 I/O 성능 및 사용률
CPU 성능 및 사용률 등


시스템 운영중 DBMS 전체의 옵티마이저 모드를 변경하는 작업은 가급적 하지 않는 것이 좋다.

📝옵티마이저 한계

잘못된 비용 계산의 한계

복잡한 쿼리문때문에 정확하지 않은 통계자료 발생

동시성 배제한 비용 계산의 한계

비용 예측시 한 개의 SQL만 실행된다는 전제로 진행하게 되는데 실제 운영 환경에서 같은 블록을 접근하는 등 상황이 발생해 대기상태가 될 수 있다.

컬럼 타입에 대한 비용 에측의 한계

날짜 유형의 데이터를 날짜 데이터 타입이 아닌 문자 데이터 타입을 컬럼으로 사용할 경우 비용 계산 방식이 달라져 예측이 어려워질 수 있다
예를 들면 날짜 데이터를 DATE타입으로 선언하면 특정 월에는 1부터 최대 31까지의 날짜만 존재하지만 YYYYMMDD 형식을 갖는 VARCHAR 타입의 데이터를 선언하면
이는 연속된 문자열이기 때문에 31일 이후의 날짜가 존재할 수 있다고 판단한다. 그 결과 예측되는 최종비용 또한 정확성이 떨어지게 된다.

 

 

발췌 : 실전 사례로 살펴보는 SQL 튜닝 비법

반응형