DB 인덱싱 전략.

HyoKwangRyu·2020년 10월 9일
2

잘 생각해보지 않았던 부분.
항상 외래키 정도를 인덱싱 컬럼으로 설정했었는데.. 더 알아볼 필요가 있다.

Mysql 기준

index?

특정 컬럼을 기준으로 메모리 영역에 목차를 생성 하는 것.

insert, update, delete 성능을 희생하는 대신 select의 성능을 높인다.
그런데 update, delete할때도 결국 데이터를 조회 하기 때문에 인덱스가 있으면 빠르게 조회됨.

-> update, delete할때, 인덱스로 지정된 컬럼을 이용하자.

MySQL은 B-tree의 확장된 개념인 B+tree로 이루어져 있다.
이번 글에서 B-tree에 대해서 깊게 다루진 않을 것.

B-tree

핵심은 데이터가 정렬된 상태로 유지되는 것

Root Node > Branch Node > Leaf Node 순으로 세 노드는 메모리에 저장된다.
각 노드에는 다음 노드를 찾기위한 키가 저장되어있다.
Leaf Node 다음에 실제 데이터가 디스크 저장소에 저장된다.

Root Node > Branch Node > Leaf Node(메모리 저장소) > 데이터 (디스크 저장소)

당연히 메모리에서 데이터를 읽는게 디스크에서 읽는것 보다 훨씬 빠르다.
결국 인덱스의 성능은
디스크 저장소 접근을 얼마나 줄일 수 있는가
Root 에서 Leaf까지의 이동 횟수를 얼마나 줄일 수 있는가에 달려있다.

인덱스의 갯수도 중요하다.
너무 많은 인덱스는 새로운 Row를 등록할때마다, 인덱스를 추가해야하고
update, delete마다 인덱스 수정이 필요하여 성능상 이슈가 있다.
그리고 인덱스 역시 공간을 차지한다.

Index key size

MySQL InnoDB 테이블의 각 row의 데이터는 페이지들 안에 나뉘어서 저장된다.
인덱스 역시 페이지 단위로 관리 된다.

페이지는 16KB 로 크기가 고정.

인덱스의 자식 노드의 개수는 페이지의 크기와 값에 의해 결정된다.
키값의 크기가 증가하면, 읽어야 할 페이지가 늘어 나고 결국 디스크를 읽는 횟수가 증가한다.

그리고 인덱스 키 값이 증가되면 캐시에 저장할 수 있는 인덱스의 갯수 또한 줄어든다. 결국은 메모리의 효율도 떨어질 수 있다.

인덱스 키 값의 크기가 증가하면
-> 페이지 내의 인덱스의 갯수가 줄어들고
-> 디스크를 읽어야할 횟수가 증가하며
-> 캐시에 저장할 수 있는 인덱스의 갯수도 줄어든다.
-> 인덱스의 키는 길면 길수록 성능이 안좋을 수 있다.

Cardinality

카디널리티(Cardinality)란 집합원의 갯수.
예를 들어 지역, 성별 등은 카디널리티가 낮다.
반대로 id, 계좌번호 등은 카디널리티가 높다.

1개의 컬럼 인덱싱

결론적으로 카디널리티가 높은 것을 인덱싱 하면 좋다.
성별을 인덱싱 하면, 50퍼 밖에 거르지 못한다.

여러 개의 컬럼 인덱싱

카디널리티가 높은순에서 낮은순으로 구성하자.

update 빈도

update가 발생하면 index를 갱신하기 때문에 성능에 좋지 않다.
수정 빈도가 적은 컬럼으로 결정하자.
꼭 필요한 경우에는 결합 인덱스로 하자.

자주 조합되는 경우

결합인덱스를 만들자.

join

기본키나 외래키 처럼 조인의 연결고리가 될 만한 컬럼들을 인덱싱 하자.

고려사항.

새로 추가된 인덱스는 기존 인덱스에 영향을 미칠 수 있다.
-> 가능한 기존 인덱스는 변경하지 말자.

지나치게 많은 인덱스는 오버헤드 가능성이 있다.
넓은 범위를 인덱스로 처리하면 오버헤드 가능성이 이따.

대부분의 경우 가장 좋은 하나의 인덱스만 사용하는 것이 여러 개의 인덱스를 사용하는 것보다 좋다.

profile
Backend Developer

0개의 댓글