DB CRUD는 많이 그리고  하는데, DB 튜닝의 꽃인 인덱스 기본 구조와 탐색 원리를 모르는 사람이  많다.

(나도  모름)

 

인덱스 기본에 대해 간략히 기술하겠다.

DB 테이블에서 데이터를 찾는 방법은 두가지다.

  1. 디비 풀스캔
  2. 인덱스 사용

디비 풀스캔은 말그대로 멀티 블락 I/O(한번에 많은 데이터를 옮길  있는 자료) 활용해 한번에 ! 읽어서 처리하는 방식이다. 

디비 풀스캔이 절대적으로  좋다고 생각하는 사람들이 많은데 절대 그렇지 않다.

where 절에 속하는 범위가 많을때(1~2년 범위로 데이터 조회) 그냥 풀스캔으로 한방에 처리하는게 훨씬 빠르고 좋다.

 

 

이유는 뭘까??

멀티블락I/O, 싱글블락I/O

DB 속도는 I/O와 관계가 있다.  I/O가 작을수록 좋다. I/O를 간략히 설명하면 실행속도가 빠른 CPU 에서 상대적으로 느린 저장장치에 데이터를 요청할때 I/O가 발생하는데

 

CPU : "아... 데이터 저장장치 너무 느리네. 나는 빠르니깐 다른 프로세스에게 CPU 넘겨 주고 할거하고있을게  읽으면 인터럽트 걸어라.

 

I/O Device: "! 알겠습니다. (데이터를 열심히 찾고) CPU님!  준비 됐습니다!"

 

I/O를 경박하게 말하면 위의 대화와 같다.

 

다시 본론으로 돌아와 풀스캔이  좋은 이유를 설명하겠다.

이유는 간단하다. 디비 풀스캔은 멀티 블락 I/O를 사용하기 때문에 I/O가 작다. 인덱스는 싱글 블락 I/O를 사용하기 때문에 I/O가 많다.

그래서 범위가 좁을땐 싱글 블락 I/O를 사용하는 인덱스가 훨씬 빠르지만(작은거 찾자고 풀스캔으로  읽으면 너무 느림) 범위가 많을땐 풀스캔이 오히려 유리하다.

 

인덱스 구조 및 원리

인덱스는 B트리 구조로 되어있다.

 

B 트리는 검색속도가 상당히 빠른 자료구조다(log n). 인덱스가 빠른 이유도 여기에 있다.

인덱스는 정렬된 데이터다. 이게 가장 중요하다. 정렬된 데이터. 그렇기 때문에 빨리 읽을  있다.

예를 살펴보자.

 

 

학생명부에서 시력이 1.0 ~1.5인 홍길동을 찾아보자 학생명부를 이름, 시력순으로 정렬했다면 아래와 같은 표가 된다.

 ※ 시력이 1.0 ~1.5인 홍길동은 2명이라고 가정

  시력 학년
이승우 1.5 4
이시연 1.2 3
탁유리 1.2 4
... ... ...
홍길동 1.0 4
홍길동 1.5 4

 

이때는 이름순으로 정렬되어 있으니 정말 소량만 스캔하면 된다.

(이름 홍길동 찾아서 시력 읽기)

 

 

반면 시력과 이름순으로 정렬해 두었다면 똑같은 두명을 찾는데도 스캔량이 많이 늘어난다.

(시력이 1.0 가서 이름 쫙 스캔, 시력 1.5가서 이름 쫙 스캔)

시력 이름 학년
0.5 이승우 4
...   3
1.0 홍길동 4
... ... ...
1.5 홍길동 4
1.5 홍길홍 4

 

인덱스 선두컬럼을 무엇으로 설정 했느냐에 따라 같은 인덱스라도 차이가 많이난다.

그럼 인덱스가 이름순으로 정렬된거 하나, 시력순으로 정렬된거 하나, 각각 있다면 어떤걸 선택해야 할까?

당연히 이름순이다. 이름찾고 시력찾는게 더 빠르니깐.

여기서 중요한 개념이 등장한다. 1. 인덱스 스캔 효율화, 2. 랜덤 액세스 최소화 두가지다.

 

인덱스 스캔 효율화는 학생 명부를 얼마나 효과적으로 빨리 읽느냐다.

 ※ 이름순으로 읽는게 더 효율적

 

랜덤 액세스 최소화는 학생명부에 없는 나머지 정보를 얻기 위해 직접 테이블을 액세스해서 비교하는 작업이다.

이때 바로 I/O가 발생한다.

 

시력순으로 정렬된 인덱스를 사용할 때 시력은 인덱스에서 알고 있으나 이름이 홍길동인지 확인해야 한다. 이때 테이블을 액세스(I/O) 해야한다.

 

물론 시력, 이름 두가지 다 인덱스에 있을때는 테이블 액세스가 발생하지 않는다.

그럼 두가지 인덱스 다 넣어서 만들면 되잖아?! 할 수 있겠지만 인생은 모든지 트레이드 오프다.

인덱스가 많아지면 초당 트랜잭션 횟수가 감소하고, 용량도 많이 차지한다.

(왜냐하면 insert 할때 인덱스 DB에도 정렬된 순서에 맞게 insert 해줘야 하니깐!)

 

 

결론 : 인덱스는 I/O 싸움이다. I/O는 최대한 적게!

 

 

 

 

+ Recent posts