간단명료

3.4 인덱스 설계 본문

친절한 SQL 튜닝/3장. 인덱스 튜닝

3.4 인덱스 설계

FeelGoood 2022. 3. 1. 19:45

3.4.1 인덱스 설계가 어려운 이유

인덱스가 많으면 다음과 같은 문제가 발생한다.

  • DML 성능 저하 (-> TPS,Transaction Per Second 저하)
  • 데이터베이스 사이즈 증가 (-> 디스크 공간 낭비)
  • 데이터베이스 관리 및 운영 비용 상승

3.4.2 가장 중요한 두 가지 선택 기준

  1. 조건절에 항상 사용하거나, 자주 사용하는 컬럼을 선정한다.
  2. '=' 조건으로 자주 조회하는 컬럼을 앞쪽에 둔다.

3.4.3 스캔 효율성 이외의 판단 기준

그 외 고려할 판단 기준

  • 수행 빈도
  • 업무상 중요도
  • 클러스터링 팩터
  • 데이터량
  • DML 부하(= 기존 인덱스 개수, 초당 DML 발생량, 자주 갱신하는 컬럼 포함 여부 등)
  • 저장 공간
  • 인덱스 관리 비용

이런 다양한 판단 기준에 대한 해석이 서로 다르기 때문에 설계자의 성향이나 스타일에 따라 결과물도 크게 달라진다. 이 중 수행빈도는 NL조인할 떄 어느 쪽에서 자주 액세스 되는지도 중요한 판단 기준이 된다.
NL조인 시 아우터 쪽(드라이빙 집합)에서의 비효율은 큰 문제가 아닐 수 있지만 이너 쪽 인덱스 스캔 과정에 비효율이 있다면 이는 성능에 큰 문제를 야기할 수 있다. NL 조인 Inner 쪽 인덱스는 '=' 조건 컬럼을 선두에 두는 것이 중요하고, 될 수 있으면 테이블 액세스 없이 인덱스에서 필터링을 마치도록 구성해야 한다.


3.4.4 공식을 초월한 전략적 설계

(page 236 참고)


3.4.5 소트 연산을 생략하기 위한 컬럼 추가

조건절에 사용하지 않는 컬럼이더라도 소트 연산을 생략할 목적으로 인덱스 구성에 포함시킴으로써 성능 개선을 도모할 수 있다. 위치는 앞뒤 중간 어디에 두어도 상관없다. '='이 아닌 조건절 컬럼들은 반드시 ORDER BY 컬럼보다 뒤쪽에 두어야 소트연산을 생략할 수 있다.
I/O를 최소화하면서 소트 연산을 생략하려면 아래 공식에 따라 인덱스를 구성하면 된다.

  1. '=' 연산자로 사용한 조건절 컬럼 선정
  2. ORDER BY 절에 기술한 컬럼 추가
  3. '=' 연산자가 아닌 조건절 컬럼은 데이터 분포를 고려해 추가 여부 결정

IN조건은 '='이 아니다.

3.3.8에서 강조했듯, IN 조건은 '='이 아니다.

select    고객번호, 고객명, 거주지역, 혈액형, 연령
from    고객
where    거주지역 = '서울'
and        혈액형 in ('A', 'O')
order by 연령

인덱스는 [거주지역 + 혈액형 + 연령] 일 때, IN 조건이 '='이 되려면 IN-List Iterator 방식으로 풀려야 한다. 그러면 UNION ALL 로 두 집합을 묶어 '연령'순으로 정렬하는 문제가 남는다.

select    고객번호, 고객명, 거주지역, 혈액형, 연령
from    고객
where    거주지역 = '서울'
and        혈액형 = 'A'
union all
select    고객번호, 고객명, 거주지역, 혈액형, 연령
from    고객
where    거주지역 = '서울'
and        혈액형 = 'O'
order by 연령

ORDER BY 절의 소트 연산을 생략하려면 위쪽 브랜치를 실행하고 이어서 아래쪽을 실행했을 때 그 결과가 연령 순으로 정렬돼야 한다. 서울에 거주하는 모든 'A'형 고객이 'O'형 고객보다 연령이 낮아야 한다.
결론적으로, 소트 연산을 생략하려면 IN 조건절이 IN-List Iterator 방식으로 풀려선 안된다. 즉, IN 조건절을 인덱스 액세스 조건으로 사용하면 안 된다. 필터 조건으로 사용해야 한다. 따라서 인덱스를 [거주지역 + 연령 + 혈액형]순으로 구성해야 한다.


3.4.6 결합 인덱스 선택도

인덱스 생성 여부를 결정할 때는 선택도가 충분히 낮은지가 중요한 판단기준이다. '선택도'란 전체 레코드 중에서 조건절에 의해 선택되는 레코드 비율 을 말하며, 선택도에 총 레코드 수를 곱해서 '카디널리티' 를 구한다.
'인덱스 선택도'는 인덱스 컬럼을 모두 '='로 조회할 때 평균적으로 선택되는 비율을 의미한다.
선택도가 높은(카디널리티가 높은) 인덱스는 효용가치가 별로 없다.테이블 액세스가 많이 발생하기 때문이다. 인덱스를 생성할 때는 선택도/카디널리티를 확인해야 한다.

결합 인덱스 컬럼 간 순서는 스캔 효율에 전혀 차이가 없다.(2.1.5 https://gyujingyujin.tistory.com/14?category=1262761)


3.4.7 중복 인덱스 제거

  • X01 : 계약ID + 청약일자
  • X02 : 계약ID + 청약일자 + 보험개시일자
  • X03 : 계약ID + 청약일자 + 보험개시일자 + 보험종료일자

    위 세 인덱스는 중복이다. X03 인덱스를 남기고, X01, X02는 삭제해도 된다.(X03 이 다 포함하고 있기 때문)
    (실습은 page 245 참고)

3.4.8 인덱스 설계도 작성

(page 249)

728x90
반응형
Comments