본문 바로가기
C.W.K.
Stream
Lesson 07 of 10 · published

JSONB와 전문 검색을 위한 GIN

~12 min · indexes, gin

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

한 값 안의 여러 항목을 역색인해

GIN은 JSONB의 키와 값, 배열 원소, tsvector의 낱말처럼 한 열 안에 여러 검색 대상을 가진 자료에 맞아. 포함 연산자 @>를 빠르게 처리해. 수백만 문서 규모에서는 tsvector와 GIN만으로도 Elasticsearch를 별도로 두지 않아도 될 수 있어.

연산자 클래스가 저장 범위를 정해

jsonb_path_ops는 주로 @> 포함 질의에 집중해 더 작을 수 있지만 모든 JSONB 연산을 지원하지는 않아. 어떤 연산자를 실제로 쓰는지 먼저 확인해.

읽기 이득과 쓰기 비용을 함께 봐

GIN은 많은 항목을 기록하므로 B-tree보다 만들고 갱신하는 비용이 클 수 있어. 또 다른 @> 질의가 있다고 해서 같은 설정이 항상 맞는 것도 아니야.

Code

JSONB GIN 인덱스·sql
CREATE TABLE events (
    id   INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    data JSONB NOT NULL
);

-- 범용 GIN: 모든 @> 쿼리 도움
CREATE INDEX events_data_gin ON events USING gin (data);

-- 더 빠르고 작은 GIN: path-ops 쿼리만
CREATE INDEX events_data_path_gin ON events USING gin (data jsonb_path_ops);

SELECT *
FROM events
WHERE data @> '{"type":"click"}';
전문 검색을 위한 GIN·sql
ALTER TABLE articles
ADD COLUMN tsv tsvector
GENERATED ALWAYS AS (to_tsvector('english', body)) STORED;

CREATE INDEX articles_tsv_gin ON articles USING gin (tsv);

SELECT id, title
FROM   articles
WHERE  tsv @@ plainto_tsquery('english', 'postgres performance')
ORDER  BY ts_rank(tsv, plainto_tsquery('english', 'postgres performance')) DESC
LIMIT  10;
배열을 위한 GIN·sql
CREATE INDEX products_tags_gin ON products USING gin (tags);

-- 'red' AND 'wool' 둘 다 태그된 product
SELECT * FROM products WHERE tags @> ARRAY['red', 'wool'];

-- 또는 이 태그들 중 아무거나
SELECT * FROM products WHERE tags && ARRAY['red', 'blue'];

External links

Exercise

@>로 조회하는 JSONB 열에 GIN 색인을 추가하고 EXPLAIN 전후를 비교해. 이어서 텍스트 열에 tsvector와 GIN 색인을 추가해 전문 검색 질의를 실행해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.