在文本搜索或模糊匹配场景中,很多人第一反应是用 LIKE '%关键字%',但这种方式在数据量大时性能极差。
其实 PostgreSQL 自带了一个被低估的强大扩展 —— pg_trgm,可以让模糊匹配性能飞跃式提升 🚀。
pg_trgm 是什么?pg_trgm(Trigram Matching)通过将字符串拆分为三元组(trigram),再基于相似度计算进行匹配。
举个例子:
字符串 "postgres" 被拆成以下 trigram:
" p", " po", "pos", "ost", "stg", "tgr", "gre", "res", "es "每个 trigram 都是连续的 3 个字符。 PostgreSQL 会在索引中存储这些 trigram,从而实现近似匹配、模糊搜索、相似度排序等高级能力。
pg_trgm 扩展在数据库中执行以下命令启用扩展:
CREATE EXTENSION IF NOT EXISTS pg_trgm;我们先创建一个简单的用户表,并插入一些中文数据:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
INSERT INTO users (name) VALUES
('张三'),
('李四'),
('王五'),
('赵六'),
('张晓明'),
('李晓华'),
('王小刚'),
('赵子龙');LIKE 进行模糊查询(传统方式)EXPLAIN ANALYZE
SELECT * FROM users WHERE name LIKE '%张%';结果问题:
Seq Scan(全表扫描)pg_trgm + GIN 索引提升性能-- 创建 trigram 索引
CREATE INDEX idx_users_name_trgm ON users USING gin (name gin_trgm_ops);然后再执行:
EXPLAIN ANALYZE
SELECT * FROM users WHERE name ILIKE '%张%';这时 PostgreSQL 会自动利用 GIN 索引,查询性能将提升几十到上百倍。
除了模糊匹配,pg_trgm 还支持相似度函数:
-- 查询与 “张小明” 最相似的记录
SELECT name, similarity(name, '张小明') AS sim
FROM users
WHERE similarity(name, '张小明') > 0.3
ORDER BY sim DESC;👉 输出结果类似:
name | sim |
|---|---|
张晓明 | 0.8 |
张三 | 0.5 |
李晓华 | 0.2 |
函数/操作符 | 说明 | 示例 |
|---|---|---|
similarity(a, b) | 返回字符串相似度(0~1) | similarity('abc', 'abcd') |
% | 相似匹配操作符 | 'abcd' % 'abc' |
<-> | 计算“距离”,越小越相似 | 'abcd' <-> 'abc' |
word_similarity(a, b) | 按单词分割计算相似度 | word_similarity('张小明', '张明') |

测试类型 | 数据量 | 查询语句 | 平均耗时 |
|---|---|---|---|
LIKE %张% | 100万行 | 无索引 | 1.25 秒 |
pg_trgm + GIN | 100万行 | 有索引 | 35 毫秒 |
⚡ 性能提升约 35 倍以上(取决于字符串长度与数据分布)
SET pg_trgm.similarity_threshold = 0.4;提高阈值 → 匹配更严格; 降低阈值 → 匹配更宽松。
SELECT * FROM users
WHERE name % '张明'
OR name ILIKE '%张%'
ORDER BY similarity(name, '张明') DESC;项目 | LIKE | pg_trgm |
|---|---|---|
是否支持索引 | ❌ 否 | ✅ 是(GIN) |
性能 | 慢 | 快 |
支持相似度排序 | ❌ 否 | ✅ 是 |
安装复杂度 | 简单 | 需启用扩展 |
中文支持 | ✅ | ✅(推荐 UTF8 编码) |
pg_trgm;App Store 截图生成器、应用图标生成器 、在线图片压缩和 Chrome插件-强制开启复制-护眼模式-网页乱码设置编码 乖猫记账,AI智能分类的最佳聊天记账App。 Elasticsearch可视化客户端工具