특정 고객의 최근 주문 20개를 조회하려 합니다. 고객 ID와 주문 시각의 복합 인덱스 순서를 어떻게 정하고, 선택한 순서가 쿼리에 맞는지 어떻게 확인하나요?
잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?
답변과 점검 포인트 펼치기답변 접기
구두 답변
정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.
복합 인덱스는 컬럼을 독립적인 목록처럼 검색하는 구조가 아니라, 앞선 컬럼을 기준으로 뒤 컬럼이 정렬되는 구조입니다. 특정 고객의 최근 주문 20개라면 (customer_id, created_at, id) 순서를 우선 검토합니다. 고객 ID 구간으로 먼저 들어간 뒤 그 안에서 주문 시각과 유일한 ID의 순서를 이용해 적은 범위를 읽을 수 있기 때문입니다. 그러나 전체 고객의 최근 주문, 고객 조건이 자주 빠지는 조회라면 created_at이 앞인 별도 접근 경로가 더 맞을 수 있습니다. 선택도가 높은 컬럼을 무조건 앞에 두는 규칙은 부족합니다.
쿼리의 탐색 경계를 먼저 그립니다
WHERE customer_id = :c ORDER BY created_at DESC, id DESC LIMIT 20 같은 요청에서는 고객 ID가 동등 조건으로 고정되므로 뒤의 시간·ID 정렬을 인덱스가 직접 활용하기 쉽습니다. 같은 시각의 주문이 있으면 id를 보조 정렬 키로 넣어 결과를 결정적으로 만듭니다. 범위 조건이 선행 컬럼에 오면 그 뒤 컬럼은 인덱스 탐색보다 필터에 가까워질 수 있으므로, 동등·범위·정렬 조합을 대표 질의로 따로 살펴보겠습니다.
인덱스를 사용했다는 표시만으로 성공이라 하지 않습니다. 선행 컬럼으로 넓은 구간을 찾고 뒤 조건으로 대부분 버리면 seek가 보여도 실제 읽기는 클 수 있습니다. 실행 계획의 추정 행과 실제 행, 인덱스에서 읽은 행과 최종 반환 행, 정렬 연산과 lookup 횟수를 비교합니다. 컬럼에 함수를 씌우거나 암묵적 형 변환을 일으키면 검색 가능한 형태가 깨질 수 있는데, 이런 조건을 검색 가능성(SARGability) 관점에서 점검합니다.
엔진과 데이터 편중을 포함해 선택합니다
SQL Server에서는 반환용 컬럼을 INCLUDE로 넣어 covering을 만들 수 있고, PostgreSQL·MySQL도 각자 INCLUDE·covering·인덱스 전용 스캔의 조건이 다릅니다. 같은 (customer_id, created_at)라도 MVCC visibility, 클러스터링 키, heap lookup 방식에 따라 실제 비용이 달라집니다. 인덱스가 정렬을 제거해도 반환 컬럼이 넓거나 고객 한 명의 주문이 매우 많으면 원본 접근이 병목일 수 있습니다. 반대로 인덱스를 넓히면 쓰기마다 더 많은 페이지와 로그를 갱신합니다.
검증은 주문이 적은 고객, 매우 큰 고객, 같은 시각이 많은 데이터, 최신 주문이 편중된 데이터에서 수행하겠습니다. 실제 통계가 갱신된 계획인지, 파라미터별 계획이 다른지도 확인합니다. 고객별 최근 조회가 핵심이면 고객 ID를 앞에 둔 인덱스를 선택하되, 전체 최신 조회를 같은 인덱스 하나로 해결하려 하지 않겠습니다. 인덱스 수를 늘리기 전에 쿼리 결과·정렬·페이지 크기·쓰기량을 함께 보고, 논리 읽기와 p99 개선이 유지 비용을 정당화하는지 판단하겠습니다.
필터가 추가되면 인덱스 순서의 판단도 달라집니다. 예를 들어 테넌트가 항상 동등 조건이라면 테넌트를 앞에 두고 고객·시각 구간을 뒤에 둘 수 있지만, 어떤 조회는 테넌트 전체의 최신 주문을 요구할 수 있습니다. 그러므로 한 인덱스로 모든 화면을 만족시키려 하지 않고, 실제 호출 비율이 높은 질의의 접근 경계를 기준으로 후보를 좁힌 뒤 통계 갱신과 파라미터 편중까지 포함해 비교하겠습니다.
득점 포인트
이해가 드러나는 지점을 확인해 보세요.
- 주요 쿼리의 동등·범위·정렬 경계를 기준으로 컬럼 순서를 정한다.
- seek 표시와 실제 읽은 행·반환 행을 구분한다.
- covering의 읽기 이득과 인덱스 폭·쓰기 비용을 비교한다.
감점 포인트
놓치기 쉬운 조건과 오해를 짚어 보세요.
- 선택도가 높은 컬럼을 항상 첫 컬럼으로 둔다고 말한다.
- seek면 항상 빠르고 scan이면 항상 느리다고 판단한다.
- 반환 컬럼을 전부 인덱스에 넣어도 비용이 없다고 본다.
더 파고들 거리
하나 더 질문하며 이해의 범위를 넓혀 보세요.
- 복합 인덱스에서 앞 컬럼은 범위 조건이고 뒤 컬럼은 정렬입니다. 정렬 생략이 가능한지 어떤 구간을 그려 보나요?
- 편중 데이터에서 통계 추정과 실제 행의 차이를 재현해 보세요.
- 페이지 커서의 보조 키를 길게 만들었습니다. 결정적 정렬의 이점과 인덱스·전송 비용을 어떻게 비교하나요?
득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.
원리부터 공부하고 싶다면
답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.