non-key column index의 이해
🏗️ 비키 열 인덱스(Non-Key Column Index)의 이해¶
1. 배경: 왜 단순히 인덱스만으로는 부족한가?¶
인덱스는 특정 행을 빠르게 찾기 위한 '이정표' 역할을 하지만, 쿼리가 인덱스에 포함되지 않은 다른 열(Column)을 요청할 때 문제가 발생합니다.
- RID Lookup / Bookmark Lookup: 인덱스에서 키를 찾은 후, 실제 데이터(나머지 열 값)를 가져오기 위해 테이블 본체(Heap 또는 Clustered Table)로 다시 이동해야 하는 과정입니다.
- 무작위 I/O (Random I/O)의 문제: 인덱스는 정렬되어 있지만, 실제 데이터 페이지는 디스크 여기저기에 흩어져 있습니다. 수천 건의 결과를 가져올 때마다 디스크의 여러 지점을 무작위로 찔러봐야 하므로 성능이 급격히 저하됩니다.
2. 해결책: 인덱스 전용 스캔 (Index-Only Scan)¶
강의에서 언급한 '선택한 열을 인덱스에 포함하는 방식'입니다.
- 개념: 인덱스 리프 노드에 실제 데이터 열의 값을 함께 저장합니다.
- 효과: 쿼리에 필요한 모든 데이터가 인덱스 안에 이미 존재하므로, 테이블 본체(Heap)로 돌아갈 필요가 없습니다. 이를 '커버링 인덱스(Covering Index)'라고 합니다.
- 성능 향상: 결과 집합의 크기에 따라 성능이 3배 이상 빨라질 수 있으며, 특히 대량의 행을 반환하는 내부 쿼리(Selector)에서 큰 위력을 발휘합니다.
3. 실무적 고려사항 및 비용¶
강의에서는 인덱스 생성 시 발생하는 '비용(Cost)'을 반드시 고려해야 한다고 강조합니다.
| 구분 | 내용 |
|---|---|
| 공간 비용 | 인덱스 리프 노드에 데이터 열을 추가하므로 인덱스 파일의 크기가 커집니다. |
| I/O 비용 | 인덱스가 비대해지면 한 번의 I/O로 읽어올 수 있는 리프 노드 수가 줄어듭니다. |
| 유지보수 비용 | 데이터가 INSERT, UPDATE, DELETE 될 때마다 인덱스도 함께 갱신해야 하므로 쓰기 성능에 영향을 줍니다. |
| 운영 전략 | 앱 구동 초기 설정 시 결정하는 것이 좋지만, 쿼리 경로가 비효율적일 경우 운영 중에도 실행 계획을 분석하여 인덱스를 추가/조정해야 합니다. |
💡 핵심 요약¶
"인덱스는 단순히 행을 찾는 도구를 넘어, 테이블 방문 자체를 생략하게 만드는 전략으로 활용될 수 있습니다. 무작위 I/O 비용이 높은 환경에서 비키 열(Non-key column)을 활용한 커버링 인덱스는 가장 강력한 튜닝 도구 중 하나입니다."