TIL

Partial Index

Partial index 정의

유용한 경우

사용 사례

  1. Soft Delete 패턴: deleted_at IS NULL인 행만 인덱싱하여 삭제되지 않은 레코드 조회를 최적화한다.
  2. 미처리 주문 조회: 전체 주문 중 status = 'PENDING'인 미결제 주문은 소수지만 가장 자주 조회되므로, 해당 행만 인덱싱한다.
  3. 활성 사용자 필터링: active = true인 사용자만 인덱싱하여 비활성 사용자를 제외한다.
  4. 이벤트 분석: 전체 이벤트 로그 중 event_type = 'SIGNUP'처럼 특정 이벤트만 분석할 때,
  5. 웹 서버 로그: 대부분의 접속이 내부 IP 대역에서 발생하지만, 외부 IP 접속만 분석할 경우 NOT (ip >= '192.168.0.0' AND ip < '192.168.255.255')로 내부 IP를 제외한다.

생성 문법

CREATE INDEX users_email_active_ix ON users (email) WHERE deleted_at IS NULL;

predicate 함의(imply)

쿼리 조건 인덱스 사용 이유
WHERE status = 'ACTIVE' AND created_at > '2024-01-01' O 인덱스 조건을 포함하면서 더 좁은 범위
WHERE status = 'ACTIVE' O 인덱스 조건과 동일
WHERE created_at > '2024-01-01' X status = 'ACTIVE' 조건이 없음
WHERE status IN ('ACTIVE', 'PENDING') X 인덱스 조건보다 넓은 범위

부분 유니크(Partial UNIQUE) 패턴

예시

  1. Soft Delete에서 이메일 유니크: 삭제된 사용자의 이메일은 재사용 가능하게 하면서, 활성 사용자끼리는 이메일 중복을 방지한다.
CREATE UNIQUE INDEX users_email_unique_active
ON users (email)
WHERE deleted_at IS NULL;
  1. 사용자당 활성 구독 하나만 허용: 한 사용자가 여러 구독 이력을 가질 수 있지만, 활성 상태인 구독은 하나만 존재하도록 강제한다.
CREATE UNIQUE INDEX subscriptions_one_active_per_user
ON subscriptions (user_id)
WHERE status = 'ACTIVE';
  1. 대표 주소 하나만 허용: 사용자가 여러 주소를 등록할 수 있지만, 기본 주소로 설정된 것은 하나만 가능하도록 한다.
CREATE UNIQUE INDEX addresses_one_primary_per_user
ON addresses (user_id)
WHERE is_primary = true;

주의점(운영/설계 관점)

레퍼런스