[친절한SQL튜닝] 5. 인덱스 튜닝 - 인덱스 설계

H.J.SHIN·2024년 12월 17일

친절한 SQL 튜닝

목록 보기
5/8
post-thumbnail

인덱스 설계


인덱스 설계의 중요성

  • 인덱스가 많으면 DML 성능 저하, 데이터베이스 사이즈 증가, 데이터베이스 관리 및 운영 비용 상승의 문제가 발생한다.
  • 인덱스 변경에 따른 시스템 변경 영향도가 매우 크기 때문에 인덱스 구성 변경도 쉽지 않다.

DML 성능 저하

  • 테이블에 인덱스가 여러 개 있으면, 신규 데이터를 입력할 때마다 인덱스들에도 데이터를 입력해야 한다.
  • 데이터를 지울 때도 여러 인덱스에서 레코드를 찾아 지워줘야 한다.
  • 이로 인해 DML 성능 저하 -> TPS 저하로 이어진다.

데이터베이스 사이즈 증가

  • 인덱스가 많으면 디스크 공간을 낭비함

데이터베이스 관리 및 운영 비용 상승

  • 데이터베이스 사이즈가 커지는 만큼 백업, 복제, 재구성 등을 위한 운영 비용도 상승



인덱스 설계

인덱스 설계 기본 공식

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

두 조건을 전재로 약간의 비효율이 있더라도 목표 성능을 만족하는 수준으로 인덱스를 구성할 수 있어야 한다.
물론 선택에 대한 판단 근거가 있어야만 한다.


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

  • 인덱스는 항상 정렬 상태를 유지하므로 ORDER BY, GROUP BY를 위한 소트 연산을 생략하여 성능을 개선할 수 있다.

  • I/O를 최소화하면서 소트 연산을 생략하는 공식
    1. '='연산자로 사용한 조건절 컬럼 선정
    2. ORDER BY절에 기술한 컬럼 추가
    3. '='연산자가 아닌 조건절 컬럼은 데이터 분포를 고려해 추가 여부 결정

  • ex)
    위 쿼리에 ORDER BY절이 있음에도 소트 연산이 발생하지 않도록 인덱스를 구성하려고 한다.
    우선 취급지점ID는 '='연산자이기 때문에 순서에 영향을 주지 않아 인덱스 구성에 포함할 수 있다.

    다음으로 ORDER BY절에 포함된 청약일자입력자ID를 소트 연산을 생략하기 위해 인덱스 구성에 포함한다.

    '='이 아닌 조건절 컬럼들도 순서에 영향을 주지 않도록 ORDER BY컬럼보다 뒤쪽에 추가할 수 있다.
    만약 쿼리를 만족하는 데이터가 적으면 인덱스에 추가하여 테이블 랜덤 액세스를 줄이는 것이 좋고, 데이터가 많으면 테이블에서 필터링할 때와 큰 성능차이가 없기 때문에 굳이 인덱스에 추가하지 않아도 된다.


결합 인덱스 선택도

  • 인덱스 생성 여부를 결정할 때 선택도가 충분히 낮은지가 중요한 판단기준이다.
  • 선택도: 전체 레코드 중에서 조건절에 의해 선택되는 레코드 비율
  • 인덱스 선택도: 인덱스 컬럼을 모두 '='로 조회할 때 평균적으로 선택되는 비율

  • 선택도가 높으면 테이블 액세스가 많이 발생한다.
  • 인덱스는 랜덤 액세스로 블록 I/O하기 때문에 선택도가 높은 인덱스는 효용가치가 별로 없다.
※ 컬럼 순서는 선택도와 관련 없다. 인덱스에 포함된 컬럼은 모두 인덱스 액세스 조건이므로 어떤 컬럼이 앞으로 오든 인덱스 스캔 범위는 똑같다.

중복 인덱스 제거

  • 인덱스가 다른 인덱스를 완전히 포함하는 경우에는 포함되는 인덱스를 삭제해도 된다.

    • ex)
    • 위 인덱스의 경우 X01과 X02가 X03에 완전히 포함된다. 이럴 경우 X01과 X02를 삭제하여도 된다.
  • 이외에도 선두컬럼의 데이터가 적거나, 동일한 인덱스 액세스 조건을 공유하는 경우에는 중복되는 인덱스를 통합할 수도 있다.

    • ex)
    • 계약ID의 평균 카디널리티가 적다면 인덱스를 통합하는 것이 더 효율적이다.

0개의 댓글