튜닝의 핵심은 랜덤 I/O와의 전쟁
1️⃣ 인덱스 ROWID는 물리적 vs 논리적 ?
- 인덱스 구조: 값 + 그 값의 위치 정보를 담은 ROWID
- 여기서 ROWID는 물리적 주소가 아닌 논리적 주소!
- 즉, 우체부 아저씨가 일일이 집을 찾아다니는 구조이기 때문에
ROWID로 레코드를 찾으러 테이블 액세스를 반복하는 것은 상당한 고비용
🐤 참고로, REDIS와 같은 메모리 DB의 인덱스의 ROWID는 물리적주소이며
여기서 말하는 인덱스는 ORACLE과 같은 디스크 DB의 인덱스입니다!
2️⃣ 클러스터링 팩터
- 같은 값을 같는 데이터가 모여있는 정도
- 클러스터링 팩터가 좋은 컬럼에 생성한 인덱스는 검색 효율이 매우 좋다!
만약, 테이블 레코드를 블록 단위로 I/O한다면 클러스터링 팩터는 효과가 있을까?
-
정답은 있다!
-
왜냐하면, 버퍼 Pinning이라는 것이 존재하기 때문이다.
버퍼 Pinning이란?
찾아낸 테이블 블록에 대한 메모리 주소값을 바로 해제하지 않고 잠시 유지하는 것
-
이로 인해, 다음 인덱스를 읽었을 때 마침 직전과 같은 테이블 블록을 가르킨다면?
래치 획득과 체인 스캔 과정을 생략하고 테이블 블록을 읽을 수 있다.
3️⃣ 인덱스 손익분기점
- 인덱스 ROWID가 논리적 주소이기 때문에, 이를 통한 테이블 액세스가 생각보다 고비용 구조다.
- 따라서, Index Range Scan이 어느 순간 Table Full Scan보다 느려지는 시점이 오는데
이를 인덱스 손익분기점이라고 한다.
Table Full Scan보다 느려지게 만드는 핵심적인 두가지 요인
- Table Full Scan: 시퀀셜 액세스 / 인덱스 ROWID: 랜덤 액세스
- Table Full Scan: Muliti Block I/O / 인덱스 ROWID: Single Block I/O
- 즉, 테이블 스캔이 항상 나쁜 것만은 아니며 인덱스 스캔이 항상 좋은 것도 아니다.
- 모든 성능 문제를 인덱스로 해결하려 해서는 안 되는 것!
- 인덱스는 다양한 튜닝 도구 중 하나일 뿐이며,
큰 테이블에서 아주 적은 일부 데이터를 빨리 찾고자 할 때 주로 사용한다.