← 기술 지식

기술 지식 / 데이터 시스템 / 데이터베이스 / 인덱스·실행 계획

검색 가능 조건·부분 인덱스·온라인 생성

원본 범위와 함수 인덱스·predicate 함의를 구분하고 시간대·파라미터 계획·상태 전환·동시 인덱스 구축과 실패 잔여를 설명합니다.

데이터베이스 · 원리·구현·운영
기술 지식 트리

인덱스 설계에서 먼저 정할 것은 빠른 실행이 아니라 같은 결과 집합을 어떤 조건으로 표현할지입니다. 원본 컬럼의 정렬 구간, 부분 인덱스가 포함하는 행 집합, 온라인 구축 중 상태는 서로 다른 문제입니다. 질의 의미를 보존한 표현을 만든 다음 옵티마이저의 실제 선택과 구축 중 자원·실패 상태를 확인합니다. 상태를 2026-03-01이라는 현지 날짜로 고정해 보면, 먼저 시간대 규칙으로 start와 next_start를 계산하고 그 두 경계를 저장 시각의 도메인에 맞춰 바인딩합니다. 그 다음 함수식과 반열린 범위의 결과 행을 대조합니다. 예상 결과가 다르면 인덱스 사용률보다 시간대 변환 또는 경계 포함 규칙을 먼저 고칩니다.

함수 계산값과 원본 컬럼의 인덱스 탐색 범위

timestamp 컬럼에 DATE 함수를 적용해 오늘과 비교하면 기존 timestamp 인덱스의 탐색 범위를 직접 사용하기 어려울 수 있습니다. 같은 의미를 created_at >= start AND created_at < next_start로 표현할 수 있다면 원본 정렬 구간을 명확히 만들 수 있습니다. 모든 함수가 무조건 인덱스를 막는다는 법칙은 아니며 엔진의 변환·특수 접근을 실제 계획으로 확인합니다.

현지 날짜의 start와 다음 날짜 start를 각각 시간대 규칙으로 계산해야 합니다. 일광절약 전환이 있는 날은 24시간과 다를 수 있어 UTC 시작에 무조건 24시간을 더하면 결과가 달라질 수 있습니다. 성능을 개선하며 업무 날짜 의미를 바꾸면 안 됩니다.

파라미터 타입·정규화와 인덱스 접근 경로

조건 먼저 확인할 것 대안
날짜 함수 비교 현지 날짜·저장 시간대 반열린 원본 범위
LOWER(email) 실제 대소문자·collation 규칙 expression index·생성 컬럼
문자열 ID와 숫자 parameter 암묵 변환의 적용 쪽 같은 도메인 타입으로 바인딩
복잡한 표현식 결정성·immutable 요구 지원되는 표현 저장·재생성

예를 들어 이메일을 대소문자 구분 없이 비교해야 한다면 LOWER(email) 결과를 저장하는 expression index나 computed/generated column을 질의 표현과 맞춰 사용할 수 있습니다. 인덱스 정의에 사용한 함수가 결정성·immutable 요구를 만족하는지, collation과 지원 타입이 맞는지, 바인딩 질의의 식이 저장된 표현과 일치하는지를 정의와 실행 계획에서 대조합니다.

정규화 정책이나 함수가 바뀌면 기존 인덱스에 저장된 표현이 새 의미와 달라질 수 있어 데이터 검증과 인덱스 재구성이 필요할 수 있습니다. 인덱스용 변환이 빠른 탐색을 돕는 것과 사용자가 말하는 동일성 의미를 정하는 것은 별개의 결정입니다.

부분 인덱스 predicate와 질의 조건의 포함 관계

pending 행만 저장한 인덱스를 쓰려면 쿼리가 pending 집합만 요구한다는 것을 옵티마이저가 판단할 수 있어야 합니다. status='pending' AND created_at<...는 후보가 되지만 status IN ('pending','failed')의 전체 결과를 그 인덱스 하나만으로 제공할 수는 없습니다.

부분 인덱스는 전체 테이블의 조건 집합입니다전체 작업 테이블. status=pending 인덱스. pending이며 기한 전인 질의predicate로 선별질의가 함의하는 범위전체 작업 테이블status=pending 인덱스pending이며 기한 전인 질의
부분 인덱스는 전체 테이블의 조건 집합입니다 화살표는 행의 포함 관계입니다. 질의 결과가 부분 집합 안이라는 근거가 있어야 누락 없이 인덱스를 사용할 수 있습니다.
그림을 글로 읽기
  • 전체 작업 테이블
  • status=pending 인덱스
  • pending이며 기한 전인 질의
  1. 전체 작업 테이블 → status=pending 인덱스: predicate로 선별
  2. status=pending 인덱스 → pending이며 기한 전인 질의: 질의가 함의하는 범위

status = :status처럼 상태를 parameter로 넘긴 prepared query가 generic plan을 쓰면, 계획을 만드는 시점에 :status가 항상 pending이라는 사실을 알 수 없을 수 있습니다. 그러면 status='pending'만 저장한 부분 인덱스로 결과를 빠짐없이 만들 수 있다고 판단하지 못해 그 인덱스를 고르지 않을 수 있으므로, 상수 조건과 parameter 조건의 실제 plan을 나란히 비교합니다.

이 비교에서 조건 표현·NULL 처리·함수·parameter plan의 추론도 함께 보되, 인덱스가 작다는 사실만으로 모든 query에 사용할 수 있다고 결론 내리지는 않습니다.

pending→done 변경은 부분 인덱스 제거 작업이고 done→pending은 삽입입니다. pending 비율이 급증하면 인덱스 크기와 유지 비용도 커집니다. 활성 행 UNIQUE로 활용할 때 탈퇴 후 이름 재사용·복구 충돌은 별도 정책입니다. 엔진마다 partial·filtered 지원이 다르므로 같은 SQL을 이식하면 된다고 가정하지 않습니다.

온라인 인덱스 생성의 스캔·변경 반영·최종 게시

기존 데이터를 읽어 인덱스를 만들면서 동시 변경도 반영하고 최종 유효 구조로 전환해야 합니다. online·concurrent 옵션은 일반 작업과 공존을 높이는 기능이지 모든 잠금·I/O·로그·추가 디스크를 없애지 않습니다. 시작·끝 메타데이터 잠금이나 오래된 transaction 대기가 남을 수 있습니다.

앞의 '스캔→동시 변경 반영→최종 게시'가 어떤 단계와 상태로 구현되는지는 제품과 버전에 따라 달라집니다. PostgreSQL concurrent build, SQL Server online build, MySQL online DDL은 지원 버전·대상·단계·잠금·실패 뒤 상태를 각각 문서와 시스템에서 대조하고, 취소 후 invalid index·임시 파일·부분 자원이 남는지 확인합니다.

이름이 존재하는지만으로 사용 가능하다고 판정하지 말고, 고유 인덱스는 기존 중복을 먼저 세고 생성 중 새 중복이 생겼을 때의 최종 실패·복구 상태까지 확인합니다.

실무 선택은 “사용 가능 여부”와 “이득”을 분리합니다. 후보 인덱스가 선택되더라도 읽기량 감소가 쓰기 p99·디스크·replica lag 비용보다 작은지 비교하고, 대표 상수와 prepared parameter 양쪽의 계획을 보존합니다. 실패 실험에서는 이름, 유효성, 잔여 파일·잠금·디스크 사용량을 각각 확인해야 재시작 가능성을 잘못 판단하지 않습니다.

인덱스 생성 전후의 용량·실행 계획 검증

실제 규모 사본에서 구축 시간·디스크 여유·로그·replica lag·잠금 대기를 측정하고 중단·재시작·실패 정리 절차를 마련합니다. 실행 완료 뒤 인덱스 유효성·대표 parameter plan·쓰기 p99를 확인합니다. 새 인덱스 때문에 일부 쿼리 계획이 오히려 나빠질 수도 있습니다.

날짜 경계·DST·NULL·정규화·상태 분포의 결과 집합을 먼저 대조한 뒤 읽기량을 비교합니다. 현재 작업에서는 이 제품들의 online DDL이나 실제 질의 plan을 실행하지 않았습니다. 본문은 접근 조건과 구축 수명 설명입니다.

후속·관련 개념

함께 읽을 문서

전체 기술 지식
선택 연습 · 관련 질문 3개

질문은 이해를 확인하는 보조 자료입니다. 학습 경로와 문서의 범위는 질문 수와 독립적입니다.