인덱스

Do_It·2023년 11월 7일

인덱스란 ?
정렬된 자료구조! 이를 통해 탐색범위를 최소화
컴퓨터가 편하고 빠르게 데이터를 찾게해주는 것

[데이터베이스의 성능 핵심]
데이터베이스 성능에 핵심은 디스크의 랜덤 I/O(접근)을 최소화 하는 것

디스크 접근을 어떻게 줄일 수 있을까?
메모리에 올라온 데이터로 최대한 요청을 처리하는 것
메모리 캐시 히트율을 높이는 것임
컴퓨터가 전원이 꺼질 경우 메모리에 데이터 유실을 고려해 WAL(Write Ahead Log)를 사용

WAL? 하나의 파일 순차적으로 끝부분부터 write을 하는
끝에서 순차적으로 디스크에 값을 넣는 것임
순차적 I/O를 발생시켜 정합성이 유지됨

인덱스를 저장하는 방식에 정렬 방식이 다르다!
-> B-Tree , Hash , Fractal 등이 있으나 일반적으로 B-Tree 인덱스가 사용 됨

[B-Tree 구조]
B-Tree 인덱스에 대해 알기 위해서는 먼저 B-Tree 자료구조에 대해 알아야함
B-Tree는 자식 2개만을 갖는 이진트리를 확장하여 N개의 자식을 가질 수 있도록 고안한 것.
좌우 자식 간의 균형이 맞지 않을 경우에는 매우 비효율적이라, 항상 균형을 맞춘다는 의미에서 균형 트리(Balanced Tree) 불림.
B-Tree는 최상위에 단 하나의 노드 만이 존재, 이를 루트 노드라함
중간 노드를 브랜치 노드 , 최하위 노드를 리프 노드라고 함

[페이지(Page)]
인덱스 저장 방식을 이해하기 위해서는 페이지를 알아야함.
페이지란? 디스크와 메모리에 데이터를 읽고 쓰는 최소 작업 단위.
일반적으로 인덱스를 포함해 PK와 테이블 등은 모두 페이지 단위로 관리 됨.
만약 1개의 레코드을 읽고 싶더라도 결국은 하나의 페이지(블럭)을 읽어야하는 것임.

그래서 페이지에 저장되는 개별 데이터의 크기를 최대한 작게하여, 1개의 페이지에 많은 데이터들을 저장할 수 있ㄷ록 하는 것이 중요함.

만약 페이지에 저장되는 데이터의 크기가 메모리에 캐싱할 수 있는 페이지의 수가 줄어들 수 있음. 또한 디스크 I/O 작업이 많아질 수 있음.

만약 레코드를 찾는데 1개의 페이지만으로 처리가 안되면 다른 페이지를 읽어야 하는데, 추가 페이지를 읽는 디스크 i/o 때문에 성능이 떨어지게 됨.
메모리의 효율도 중요한데, 디스크 i/o 를 통ㄹ해 페이지를 읽어오면 버퍼풀이라는 메모리에 캐싱해둠.
그런데 개별 데이터의 크기가 커지면 페이지 자체의 크기가 커지고 메모리에 캐싱해둘 수 있는 페이지의 수가 줄어듬
-> DB 성능 개선 혹은 쿼리 튜닝은 디스크 i/o 자체를 줄이는 것이 핵심인 경우가 많음

[클러스터 인덱스]
1.클러스터 인덱스는 데이터 위치를 결정하는 키 값이다.
2.MySQL의 PK는 클러스터 인덱스다.
3.MySQL에서 PK를 제외한 모든 인덱스는 PK를 가지고 있다.

클러스터 키 순서에 따라서 데이터 저장 위치가 변경됨
-> 클러스터 키 삽입/갱신시에 성능 이슈 발생!

장점
1.PK를 활용한 검색이 빠름, 특히 범위 검색!
2.세컨더리 인덱스들이 PK를 가지고 있어 커버링에 유리함

커버링?
인덱스가 가진 값만으로도 데이터를 내려줄 수 있어서 테이블까지 접근하지 않는 것!

[B-Tree 인덱스의 구조]
인덱스는 페이지 단위로 저장되며 인덱스 키를 바탕으로 항상 정렬된 상태를 유지함.
정렬된 인덱스 키를 따라서 리프 노드(인덱스, PK) 쌍으로 저장 되어 있음.

B-Tree 인덱스
루트 노드에는 인덱스 키와 리프 노드 페이지 번호 값 존재
리프 노드의 페이지에는 인덱스 키와 PK 값이 존재

인덱스를 타면
1. 루트 노드에서 인덱스 키에 맞는 리프 노드 페이지 번호 값 찾고
2. 리프 노드에서 위에서 찾은 페이지 번호에 해당하는 페이지를 찾고
3. 그 페이지 안에서 인덱스 키와 맞는 PK 값을 찾음

인덱스는 테이블과 독립적인 저장 공간이므로
인덱스를 통해 데이터를 조회하기 위해서는 먼저 PK를 찾은 것임

[인덱스 주의 사항]
옵티마이저는 인덱스를 통해 레코드 1건을 읽는 것이 테이블 통해 직접 읽는 것 보다 4~5배 정도 비용이 더 많이 드는 것으로 예측함.
인덱스를 통해 레코드 1건 읽는 비용 = 테이블 통해지 직접 읽는 비용 * 4 or 5
-> 즉, 인덱스를 사용하는데 드는 비용이 테이블 레코드의 전체 건수를 읽는 비용보다 커질 경우에는 비효율적이라는 것
이럴 경우네는 옵티마이저는 인덱스를 이용하지 않고 테이블 전체를 읽어서 처리함!

인덱스는 값이 변형되는 경우에 사용될 수 없음

인덱스는 정순으로 검색하는 것이 효율적임

인덱스를 무조건으로 생성하는 것은 좋지 않음

인덱스를 사용하면 조회 성능을 높일 수 있지만, 쓰기나 갱신의 성능이 낮출 수 밖에 없어서 균형을 잡는게 중요함

profile
오늘의 노력이 내일의 성장으로 이어지고 있음을

0개의 댓글