Overview
A GIN index creates one entry per element of a composite value, so a single row can add hundreds of entries. Add one once full-text search, JSONB containment, or array overlap queries show sequential scans, and expect larger indexes and slower writes in exchange. Confirm the planner uses it with EXPLAIN (query-plan).
Rules
- Operators:
@@fortsvector;@>,<@,?,?|,?&,@?,@@forjsonb(defaultjsonb_ops);@>,<@,&&for arrays.jsonb_path_opsis smaller and faster but supports only@>,@?, and@@. fastupdate(default on) buffers inserts in a pending list that vacuum orgin_clean_pending_list()merges; a large pending list slows queries.- GiST updates and builds faster than GIN, but GIN answers large-vocabulary text queries faster.
- Build on live tables with
CREATE INDEX CONCURRENTLY.
CREATE INDEX idx_articles_fts ON articles USING gin (search_vec);
SELECT id FROM articles WHERE search_vec @@ to_tsquery('english', 'postgres & index');
CREATE INDEX idx_events_data ON events USING gin (data);
SELECT * FROM events WHERE data @> '{"type": "purchase"}';Related
- btree-index: the default for scalar equality and range.
- jsonb-path: jsonpath queries and which ones GIN accelerates.
- query-plan: expect a Bitmap Index Scan on the GIN.
- postgres-indexes: index strategy.
- postgres-full-text-search: tsvector setup.