博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,
15年
工作经验,精通Java编程
,高并发设计
,Springboot和微服务
,熟悉Linux
,ESXI虚拟化
以及云原生Docker和K8s
,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea
GIN(Generalized Inverted Index,通用倒排索引)是 PostgreSQL 中用于高效处理多值数据类型的索引,类似于 Elasticsearch 的倒排索引。它通过将“键-值”关系反转(键是数据元素,值是包含该元素的行),加速对数组、全文搜索、JSONB 等复杂数据类型的查询。
-- 基本语法
CREATE INDEX index_name ON table_name USING GIN (column_name);
-- 指定操作符类(如 JSONB 的 jsonb_path_ops)
CREATE INDEX idx_gin_json ON table USING GIN (jsonb_column jsonb_path_ops);
全文搜索(tsvector
)
-- 创建列并索引
ALTER TABLE articles ADD COLUMN content_tsv tsvector;
UPDATE articles SET content_tsv = to_tsvector('english', content);
CREATE INDEX idx_gin_tsv ON articles USING GIN (content_tsv);
-- 查询示例
SELECT * FROM articles WHERE content_tsv @@ to_tsquery('postgres & search');
数组类型
CREATE TABLE products (tags text[]);
CREATE INDEX idx_gin_array ON products USING GIN (tags);
-- 查询包含元素 'electronics'
SELECT * FROM products WHERE tags @> ARRAY['electronics'];
JSON/JSONB
CREATE TABLE logs (data jsonb);
CREATE INDEX idx_gin_jsonb ON logs USING GIN (data);
-- 查询 JSONB 键或路径
SELECT * FROM logs WHERE data @> '{"user": "alice"}';
SELECT * FROM logs WHERE data ? 'error';
范围类型(Range Types)
CREATE INDEX idx_gin_range ON reservations USING GIN (period);
SELECT * FROM reservations WHERE period && '[2023-10-01, 2023-10-15]';
GIN 支持自定义操作符类,优化特定查询模式:
-- 使用 jsonb_path_ops 缩小索引体积
CREATE INDEX idx_gin_json_ops ON logs USING GIN (data jsonb_path_ops);
@@
操作符)。@>
, &&
, =
)。@>
, ?
, ?|
)。&&
)。pg_trgm
模糊匹配(需启用扩展)。以下是基于 PostgreSQL GIN 索引不同适用场景的具体示例,每个例子均展示索引的创建和查询方式,并解释其适用性:
tsvector
类型)场景:快速搜索文章内容中的关键词组合(如同时包含“数据库”和“优化”的文章)。
示例:
-- 创建表并添加 tsvector 列
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
content_tsv TSVECTOR -- 存储分词后的向量
);
-- 将 content 字段内容转换为 tsvector 并填充
UPDATE articles SET content_tsv = to_tsvector('english', content);
-- 创建 GIN 索引
CREATE INDEX idx_gin_articles ON articles USING GIN (content_tsv);
-- 查询包含 'postgres' 且 'search' 的文章
SELECT * FROM articles
WHERE content_tsv @@ to_tsquery('postgres & search');
为什么适合 GIN 索引:
GIN 索引将每个关键词映射到包含它的文档行,支持布尔逻辑(&
、|
),适合多关键词组合搜索。
场景:筛选包含特定标签的商品(如标签数组中包含“electronics”的商品)。
示例:
-- 创建带数组字段的表
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT,
tags TEXT[] -- 存储商品标签数组
);
-- 创建 GIN 索引
CREATE INDEX idx_gin_tags ON products USING GIN (tags);
-- 查询包含 'electronics' 标签的商品
SELECT * FROM products
WHERE tags @> ARRAY['electronics']; -- @> 表示“包含”
为什么适合 GIN 索引:
GIN 索引会为数组中的每个元素建立倒排列表,加速 @>
(包含)、&&
(重叠)等数组操作符。
场景:快速检索 JSON 日志中的特定字段(如查找 user
字段值为 alice
的日志)。
示例:
-- 创建 JSONB 列的表
CREATE TABLE logs (
id SERIAL PRIMARY KEY,
data JSONB -- 存储 JSON 日志
);
-- 创建 GIN 索引(使用 jsonb_path_ops 压缩索引大小)
CREATE INDEX idx_gin_logs ON logs USING GIN (data jsonb_path_ops);
-- 查询 data 字段中包含 {"user": "alice"} 的日志
SELECT * FROM logs
WHERE data @> '{"user": "alice"}'; -- @> 表示“包含指定 JSON 结构”
-- 查询包含 'error' 键的日志
SELECT * FROM logs
WHERE data ? 'error'; -- ? 表示“包含键”
为什么适合 GIN 索引:
jsonb_path_ops
操作符类将 JSON 路径哈希为更紧凑的形式,支持高效的结构化查询(@>
)和键存在性检查(?
)。
场景:查找与给定时间段重叠的预订记录(如 2023-10-01 至 2023-10-15)。
示例:
-- 创建带范围类型的表
CREATE TABLE reservations (
id SERIAL PRIMARY KEY,
period TSRANGE -- 存储时间范围
);
-- 创建 GIN 索引
CREATE INDEX idx_gin_period ON reservations USING GIN (period);
-- 查询与 [2023-10-01, 2023-10-15] 重叠的预订
SELECT * FROM reservations
WHERE period && '[2023-10-01, 2023-10-15]'::TSRANGE; -- && 表示“范围重叠”
为什么适合 GIN 索引:
GIN 索引支持范围类型的重叠操作符(&&
),适合快速筛选时间、数值等范围重叠的场景。
pg_trgm
模糊匹配场景:模糊搜索用户名(如匹配类似 joh
的 john
或 johan
)。
示例:
-- 启用 pg_trgm 扩展
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- 创建表并添加 GIN 索引
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT
);
-- 使用 gin_trgm_ops 操作符类创建索引
CREATE INDEX idx_gin_trgm ON users USING GIN (username gin_trgm_ops);
-- 模糊查询用户名包含 'joh' 的用户
SELECT * FROM users
WHERE username ILIKE '%joh%'; -- 或使用更高效的正则表达式
为什么适合 GIN 索引:
gin_trgm_ops
将文本拆分为三元组(trigram),索引支持模糊匹配(LIKE
、ILIKE
、~
等),比 B-Tree 更适合模糊搜索。
场景 | 索引字段类型 | 典型操作符 | 查询特点 |
---|---|---|---|
全文搜索 | tsvector |
@@ |
多关键词组合匹配 |
数组查询 | TEXT[] |
@> 、&& 、= |
元素包含或重叠 |
JSONB 查询 | JSONB |
@> 、? 、`? |
` |
范围重叠 | TSRANGE |
&& |
时间、数值范围重叠筛选 |
模糊匹配 | TEXT + pg_trgm |
LIKE 、~ |
部分字符串匹配(如 %joh% ) |
何时选择 GIN 索引:
特性 | GIN | GiST |
---|---|---|
查询速度 | 更快(精确匹配) | 稍慢(支持近似匹配) |
写入性能 | 较低(索引更复杂) | 较高 |
数据一致性 | 需要定期维护(如 VACUUM) | 自动维护 |
适用场景 | 多值精确查询(如 JSONB、数组) | 范围查询、几何数据、模糊搜索 |
gin_fuzzy_search_limit
限制模糊查询结果数。VACUUM
或 REINDEX
优化索引性能。jsonb_path_ops
减少索引大小。使用 GIN 索引当:
避免 GIN 索引当: