deleted_at IS NULL인 행만 인덱싱하여 삭제되지 않은 레코드 조회를 최적화한다.status = 'PENDING'인 미결제 주문은 소수지만 가장 자주 조회되므로, 해당 행만 인덱싱한다.active = true인 사용자만 인덱싱하여 비활성 사용자를 제외한다.event_type = 'SIGNUP'처럼 특정 이벤트만 분석할 때,NOT (ip >= '192.168.0.0' AND ip < '192.168.255.255')로 내부
IP를 제외한다.CREATE INDEX ... WHERE predicate형태로 한다.WHERE뒤 predicate가 “인덱스에 들어갈 행의 범위”를 결정한다.CREATE INDEX users_email_active_ix ON users (email) WHERE deleted_at IS NULL;
CREATE INDEX orders_active_ix ON orders (created_at) WHERE status = 'ACTIVE'; 인덱스가 있을 때:| 쿼리 조건 | 인덱스 사용 | 이유 |
|---|---|---|
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 | 인덱스 조건보다 넓은 범위 |
x < 1이면 x < 2도 만족한다는 단순한 관계는 인식하지만, status != 'DELETED'와 status = 'ACTIVE'의 관계 같은 복잡한 논리는 인식하지 못한다.UNIQUE와 결합해 “조건을 만족하는 행들끼리만 유니크”를 강제할 수 있다.CREATE UNIQUE INDEX users_email_unique_active
ON users (email)
WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX subscriptions_one_active_per_user
ON subscriptions (user_id)
WHERE status = 'ACTIVE';
CREATE UNIQUE INDEX addresses_one_primary_per_user
ON addresses (user_id)
WHERE is_primary = true;