Postgres 17 jsonb 인덱스 — '느린 쿼리' 의 진짜 원인
jsonb 컬럼에 GIN 인덱스를 박았는데 쿼리는 여전히 느렸다. EXPLAIN 결과의 한 줄.
ETL 결과를 Postgres 의 jsonb 컬럼 (payload) 에 저장하고 있었다. 검색은 주로 payload @> '{"kind": "rss"}' 형식.
데이터가 100만 행을 넘은 후부터 같은 쿼리가 1.4초.
GIN 인덱스를 박으면 빨라진다는 글을 봤다.
CREATE INDEX idx_payload_gin ON events USING gin (payload);
배포. 다음 날 쿼리 — 여전히 1.3초. 인덱스가 안 쓰이고 있었다.
EXPLAIN
Seq Scan on events (cost=0.00..28471.00 ...)
Filter: ((payload -> 'kind') = '"rss"'::jsonb)
payload @> '{"kind": "rss"}' 가 ORM (SQLAlchemy) 단에서 payload -> 'kind' = '"rss"' 로 변환되고 있었다. 후자는 GIN 인덱스가 안 쓰인다.
두 가지 인덱스, 두 가지 쿼리
@> (containment) 쿼리에는 일반 GIN 인덱스.
payload->'kind' 형 추출에는 표현식 인덱스:
CREATE INDEX idx_payload_kind ON events ((payload -> 'kind'));
ORM 한 줄 수정
SQLAlchemy 에서 Event.payload.contains({"kind": "rss"}) 가 @> 로 변환된다. 의도한 쿼리로 명시.
결과
같은 쿼리 1.3초 → 8ms.
다음에는 다르게 할 한 가지
ORM 이 어떤 SQL 을 만드는지 반드시 EXPLAIN 으로 확인한다. “GIN 박았으니 빠르겠지” 가 아니라 “GIN 이 정말 쓰이고 있나” 를 봐야 한다. 인덱스는 박은 게 아니라 쓰이는 것 이 본질.
🛒 이 글과 어울리는 추천 상품
위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.