C.W.K.
Stream
Lesson 07 of 10 · published

JSONB 와 Full-Text 위한 GIN 인덱스

~12 min · indexes, gin

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

GIN — Generalised Inverted iNdex

B-tree 가 행당 한 값 인덱스. GIN 이 행당 여러 값 인덱스 — 텍스트 필드 안 단어들, JSONB document 안 키들, array 안 요소들. 'inverted' 부분 의미: 각 값에 대해 GIN 이 그 값 포함하는 행 리스트 저장 (책 색인이랑 같음).

JSONB containment

JSONB 의 GIN 킬러 use case 가 containment 연산자 @>: "이 sub-document 포함하는 JSONB 행". GIN 인덱스 없으면 모든 행 파싱 + 체크. 있으면 직접 lookup.

Full-text search

tsvector 컬럼의 GIN 이 "이 단어들 포함하는 document 행" 을 ms 단위로 답함, 수백만 article 에서 — Elasticsearch 불필요.

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"}';
Full-text search 위한 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;
Array 위한 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 추가하고 full-text 쿼리 실행.

Progress

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

댓글 0

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

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