시간 기반 고유성 문제 해결: Temporal Constraints
PostgreSQL 18의 Temporal Constraints는 시간 기반 데이터의 고유성 문제를 해결하기 위해 도입되었습니다. 이는 주로 다음과 같은 방식으로 작동합니다:
-
WITHOUT OVERLAPS구문:UNIQUE (column_name, valid_period WITHOUT OVERLAPS)와 같이WITHOUT OVERLAPS키워드를 사용하여 지정된 범위 컬럼(daterange또는timestamprange)이 중복되지 않도록 강제합니다. 이는 특정 사용자가 동시에 여러 활성 구독을 가질 수 없도록 하는 등의 시나리오에 매우 효과적입니다. -
범위 타입 활용: 제약 조건에 사용되는 키 컬럼은 반드시
daterange,timestamprange와 같은 범위 타입이어야 합니다. 이를 통해 강력한 범위 연산자를 활용할 수 있습니다.
예시: 사용자 구독 관리
사용자 구독 관리를 예로 들어보면, 각 사용자는 특정 기간 동안 하나의 활성 구독만 가질 수 있도록 할 수 있습니다. 다음은 subscriptions 테이블에 Temporal Constraints를 적용하는 SQL 예시입니다:
sql
CREATE TABLE subscriptions (
user_id uuid NOT NULL,
type VARCHAR(50) NOT NULL,
valid_period daterange NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
UNIQUE (user_id, valid_period WITHOUT OVERLAPS)
);
이 제약 조건은 user_id와 valid_period가 중복되지 않도록 보장하여, 한 사용자가 동일한 기간에 여러 구독을 가질 수 없도록 합니다. 과거 구독은 허용되지만, 현재 활성 구독은 하나만 가능합니다.
주의사항: GIST vs B-Tree 인덱스 및 btree_gist 확장
Temporal Constraints에 사용되는 범위 컬럼은 GIST 인덱스를 활용하는 반면, uuid와 같은 다른 컬럼은 B-Tree 인덱스를 사용합니다. 이 두 인덱스 타입의 조합으로 인해 제약 조건 생성 시 오류가 발생할 수 있습니다. 이를 해결하기 위해서는 CREATE EXTENSION btree_gist; 명령을 통해 btree_gist 확장을 활성화해야 합니다. 이 확장은 B-Tree 인덱스 타입의 데이터를 GIST 인덱스에서 사용할 수 있도록 지원합니다.
활성 구독 조회
‘아이스크림 콘’ 연산자(@>)를 사용하여 특정 날짜에 유효한 구독을 쉽게 조회할 수 있습니다. 예를 들어, '2025-01-01'::date에 활성 상태인 모든 구독을 찾는 쿼리는 다음과 같습니다:
sql
SELECT *
FROM subscriptions
WHERE valid_period @> '2025-01-01'::date;