커버링 인덱스와 인덱스 전용 스캔
쿼리가 테이블 힙에 전혀 접근하지 않도록 열을 포함합니다.
커버링 인덱스와 인덱스 전용 스캔은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
힙 페치 복습
앞서 일반 B-트리는 인덱싱된 열과 행 포인터만 저장하므로, 인덱스가 일치하는 행을 찾은 뒤에도 엔진은 다른 열을 읽기 위해 테이블로 이동해야 한다고 배웠습니다. 이 이동이 바로 힙 페치이며, 커버링 인덱스는 이 비용을 없애도록 설계되었습니다.
면접관은 인덱스가 테이블에 접근하지 않고 쿼리에 완전히 답할 수 있는 이유를 이해하고 있는지 확인하기 위해 커버링 인덱스에 관해 질문합니다.
'커버링'의 의미
쿼리에 필요한 모든 열이 SELECT, WHERE, ORDER BY 및 GROUP BY에 포함되어 있으면 인덱스가 쿼리를 커버한다고 합니다.
이 조건이 충족되면 엔진은 인덱스만 읽고 테이블을 전혀 방문하지 않습니다. PostgreSQL에서는 이를 인덱스 전용 스캔이라고 하며, SQL 서버를 비롯한 다른 시스템에서는 커버링 인덱스라고 합니다. 그 결과 페이지 읽기가 줄고 쿼리가 더 빨라집니다.
예제로 살펴보기: 커버되는 쿼리
쿼리에 customer_id와 order_date만 필요하다고 가정해 보겠습니다. 정확히 이 두 열로 구성된 복합 인덱스에는 쿼리가 요청하는 모든 정보가 있으므로 인덱스만으로 처리할 수 있습니다.
CREATE INDEX idx_orders_cust_date
ON orders (customer_id, order_date);
-- Covered: both selected columns are in the index
SELECT customer_id, order_date
FROM orders
WHERE customer_id = 42;열 하나만 추가해도 커버링이 깨집니다
인덱스에 없는 열을 추가하면 커버링이 사라져 엔진이 해당 열을 가져오기 위해 힙을 조회해야 합니다.
여기서는 total이 인덱스에 없으므로 customer_id가 탐색을 이끌더라도 일치하는 모든 행에서 total을 읽기 위한 힙 페치가 발생합니다.
-- NOT covered: total is not in the index, forces heap fetches
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;INCLUDE 절
total을 네 번째 키 열로 추가할 수도 있지만, 이 열로 필터링하거나 정렬하지 않는다면 트리의 정렬 순서에 공간을 낭비하게 됩니다. 더 깔끔한 방법은 INCLUDE입니다(PostgreSQL과 SQL 서버에서 지원). 이 방법은 추가 열을 정렬 키의 일부가 아닌 페이로드로 인덱스의 리프에만 저장합니다.
이제 검색 가능한 인덱스 부분을 불필요하게 키우지 않고도 쿼리를 커버할 수 있습니다.
CREATE INDEX idx_orders_cust_date_inc
ON orders (customer_id, order_date)
INCLUDE (total);
-- Now covered: total is carried in the leaf
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;키 열과 포함 열 비교
면접관에게 깊은 인상을 줄 수 있는 정확한 구분은 다음과 같습니다.
- 키 열은 정렬 순서를 정의하며 탐색과 범위 스캔에 사용할 수 있습니다. 왼쪽 우선 접두사 규칙을 따릅니다.
- 포함 열은 리프에 추가 데이터로만 저장됩니다. 검색할 수는 없지만 인덱스가 더 많은 쿼리를 커버할 수 있게 합니다.
간단한 기준은 다음과 같습니다. 필터링하거나 정렬하는 열은 키에 넣고, 반환만 하는 열은 INCLUDE에 넣습니다.
MySQL/InnoDB: 클러스터형 인덱스의 특징
데이터베이스별 차이를 이해하고 있음을 보여 주세요. InnoDB (MySQL) 테이블은 기본 키를 기준으로 클러스터형으로 구성됩니다. 따라서 보조 인덱스에는 기본 키 열이 암묵적으로 포함됩니다. 그러므로 보조 인덱스는 인덱싱된 열과 기본 키 열만 선택하는 모든 쿼리를 자동으로 커버하며, INCLUDE 절이 필요하지 않습니다(MySQL에는 INCLUDE가 없습니다).
커버링이라는 개념은 보편적이지만 문법과 자동으로 따라오는 열은 데이터베이스 엔진마다 다릅니다.
인덱스 전용 스캔 검증
EXPLAIN으로 커버링을 증명합니다. PostgreSQL의 실행 계획 노드에는 Index Scan 대신 인덱스 전용 스캔이 표시됩니다. EXPLAIN (ANALYZE)에서 Heap Fetches: 0인지 확인하세요. 이것이 테이블에 접근하지 않았다는 확실한 신호입니다.
인덱스 전용 스캔을 예상했는데 힙 페치가 발생하는 Index Scan이 보인다면, 선택한 열 중 하나가 인덱스에 빠져 있는 것입니다.
EXPLAIN (ANALYZE)
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;
-- Look for: Index Only Scan ... Heap Fetches: 0PostgreSQL 가시성 맵의 주의점
추가 점수를 받을 수 있는 PostgreSQL의 미묘한 특징이 있습니다. 페이지가 가시성 맵에서 모든 행이 보이는 상태로 표시되지 않았다면 인덱스 전용 스캔도 힙에 접근할 수 있습니다. 대규모 업데이트 후에는 VACUUM을 실행해 가시성 맵을 최신 상태로 유지해야 합니다. 그렇지 않으면 Heap Fetches가 늘어나 '인덱스 전용'이라는 이점이 줄어듭니다.
-- Keeps the visibility map fresh so index-only scans stay heap-free
VACUUM ANALYZE orders;NOT: 폭넓은 커버링 인덱스를 만들지 말아야 할 때
커버링 인덱스는 공짜가 아닙니다. INCLUDE에 열을 많이 넣으면 인덱스가 커져 캐시를 더 차지하고 쓰기를 느리게 합니다(관련된 쓰기가 발생할 때마다 인덱스도 업데이트됩니다). 다음과 같은 절충점을 설명해야 합니다.
- 사용량이 높고 조회 범위가 좁으며 자주 실행되는 읽기 쿼리에는 매우 유용합니다.
- 혹시 필요할지 모른다는 이유로 모든 열을 넣는 용도로 사용하면 좋지 않습니다.
행 전체가 아니라 중요한 쿼리만 커버하세요.
면접에서 이렇게 설명하세요
깔끔한 요약은 다음과 같습니다.
'커버링 인덱스는 쿼리가 참조하는 모든 열을 포함하므로 엔진은 힙 페치를 건너뛰고 인덱스만으로 처리할 수 있습니다. 즉, 인덱스 전용 스캔이 가능합니다. 검색하는 열은 키에 넣고 반환만 하는 열은 INCLUDE에 넣으며, EXPLAIN ANALYZE로 힙 페치 수가 0인지 확인합니다. 또한 쓰기 속도를 지키기 위해 인덱스를 좁게 유지합니다.'
빠른 확인
커버링 여부와 각 열을 배치할 올바른 위치를 판단해 보세요.
복습: 커버링 인덱스
핵심 요점:
- 인덱스가 쿼리에 필요한 모든 열을 보유하면 쿼리를 커버하며, 힙 페치 없이 인덱스 전용 스캔을 수행할 수 있습니다.
- 키 열은 탐색을 이끌고 왼쪽 우선 접두사 규칙을 따릅니다. INCLUDE 열은 커버링을 위한 리프 전용 페이로드입니다.
- InnoDB 보조 인덱스에는 기본 키가 암묵적으로 포함됩니다.
EXPLAIN (ANALYZE)로 확인하고Heap Fetches를 살펴보세요. PostgreSQL에서는VACUUM을 최신 상태로 유지해야 합니다.- 쓰기 성능을 지키려면 커버링 인덱스를 좁게 유지하세요.
다음: 반대 측면, 인덱스가 실제로 성능을 해치는 경우입니다.
자주 묻는 질문
“커버링 인덱스와 인덱스 전용 스캔” 강의는 무료인가요?
네 — “커버링 인덱스와 인덱스 전용 스캔” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“커버링 인덱스와 인덱스 전용 스캔”에서 뭘 배우나요?
쿼리가 테이블 힙에 전혀 접근하지 않도록 열을 포함합니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“커버링 인덱스와 인덱스 전용 스캔” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- B-트리 인덱스와 그 효과
- 복합 인덱스 열 순서
- 커버링 인덱스와 인덱스 전용 스캔
- 인덱스가 해가 되는 경우: 쓰기와 선택도