1. 배경
개발자 친구들과 이야기를 하던중 sql tuning작업을 통해 조회 쿼리 속도를 높였다는 이야기를 들었습니다.
막연하게 떠오르는 생각은 "아! 당연히 Indexing을 했겠구나" 였지만 그때 문득든 생각이 있습니다.
Indexing은 쿼리 조회 속도를 높이고 Index를 갱신를 갱신하기 때문에 CUD에 대해서는 느리다
그렇다면 로그를 남기는 것과 유사한 기능을 제외하고, 많은 비즈니스 기능은 빠른 조회를 필요로하는데 이런 테이블에 전부 인덱싱을 해야하는게 좋을까?
제가 찾은 결론부터 말하면 "아니다" 입니다.
DB에서 데이터를 스캔하는 방식은 풀스캔(Full Scan)과 인덱스 스캔(Index Scan)이 있습니다.
위의 친구같은 경우는 풀스캔으로 되어있던 방식을 인덱스 스캔으로 변경하여 조회 속도를 높인 케이스입니다.
2. 스캔 종류
1. 풀스캔(Full Scan)
- Application에서 SELECT * FROM USER WHERE ID = 10; 이라는 쿼리요청이 온다.
- 테이블 전체 데이터를 디스크에서 메모리로 옮긴 후 모든 데이터를 조사해서 ID가 10인 USER를 반환한다.
2. 인덱스 스캔(Index Scan)
- Application에서 SELECT * FROM USER WHERE ID = 10; 이라는 쿼리요청이 온다.
- 인덱스에서 필요한 데이터가 있는곳을 조사해서 필요한 데이터 블록만 읽는다. (인덱스를 조회해서 필요한 블록만 읽는다)
- ID가 10인 한건의 데이터가 들어있는 USER 테이블의 데이터 블록만 선택적으로 읽고 반환한다.
2-1 인덱스 구조
인덱스 구조에대한 글이 아니라서 가볍게 설명하겠습니다
1) B 트리
- 루트, 브랜치, 리프 구조로 리프노드에 데이터블럭의 위치를 저장한다
2) 해시테이블
- 해시함수를 사용하여 변환한 값을 인덱스로 사용하여 키와 데이터를 저장하는 구조입니다.
3. 그렇다면 언제 풀스캔이 유리한가?
테이블의 데이터를 모두 가져가야 하는경우
테이블의 데이터가 많이 없는 경우
풀스캔은 한번의 I/O로 가능한 한 크기의 데이터를 읽어서 I/O수를 줄여줍니다.
위의 경우에서 인덱스 스캔을 하게 된다면 읽어야 하는 데이터 블록이 늘어나고, 하나씩 읽어가며 I/O횟수도 늘어납니다.
항상 인덱싱을 하는게 좋은게 아니라,
특정 키 조회를 자주 쓸때, 필요한 인덱스 구조를 고민해보고 작성해야 한다고 생각합니다.