首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PostgreSQL `pg_trgm` 扩展实现高效模糊查询实践

PostgreSQL `pg_trgm` 扩展实现高效模糊查询实践

作者头像
井九
发布2025-10-31 08:36:31
发布2025-10-31 08:36:31
2500
代码可运行
举报
文章被收录于专栏:四楼没电梯四楼没电梯
运行总次数:0
代码可运行

在文本搜索或模糊匹配场景中,很多人第一反应是用 LIKE '%关键字%',但这种方式在数据量大时性能极差。 其实 PostgreSQL 自带了一个被低估的强大扩展 —— pg_trgm,可以让模糊匹配性能飞跃式提升 🚀。


🧠 一、pg_trgm 是什么?

pg_trgm(Trigram Matching)通过将字符串拆分为三元组(trigram),再基于相似度计算进行匹配。

举个例子: 字符串 "postgres" 被拆成以下 trigram:

代码语言:javascript
代码运行次数:0
运行
复制
"  p", " po", "pos", "ost", "stg", "tgr", "gre", "res", "es "

每个 trigram 都是连续的 3 个字符。 PostgreSQL 会在索引中存储这些 trigram,从而实现近似匹配、模糊搜索、相似度排序等高级能力。


🧩 二、启用 pg_trgm 扩展

在数据库中执行以下命令启用扩展:

代码语言:javascript
代码运行次数:0
运行
复制
CREATE EXTENSION IF NOT EXISTS pg_trgm;

⚙️ 三、创建测试表与数据

我们先创建一个简单的用户表,并插入一些中文数据:

代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT
);

INSERT INTO users (name) VALUES
('张三'),
('李四'),
('王五'),
('赵六'),
('张晓明'),
('李晓华'),
('王小刚'),
('赵子龙');

🔍 四、使用 LIKE 进行模糊查询(传统方式)

代码语言:javascript
代码运行次数:0
运行
复制
EXPLAIN ANALYZE
SELECT * FROM users WHERE name LIKE '%张%';

结果问题:

  • 扫描方式:Seq Scan(全表扫描)
  • 当表数据量大(百万级)时,性能极差。

⚡ 五、使用 pg_trgm + GIN 索引提升性能

代码语言:javascript
代码运行次数:0
运行
复制
-- 创建 trigram 索引
CREATE INDEX idx_users_name_trgm ON users USING gin (name gin_trgm_ops);

然后再执行:

代码语言:javascript
代码运行次数:0
运行
复制
EXPLAIN ANALYZE
SELECT * FROM users WHERE name ILIKE '%张%';

这时 PostgreSQL 会自动利用 GIN 索引,查询性能将提升几十到上百倍。


🧪 六、相似度查询与排序

除了模糊匹配,pg_trgm 还支持相似度函数

代码语言:javascript
代码运行次数:0
运行
复制
-- 查询与 “张小明” 最相似的记录
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 倍以上(取决于字符串长度与数据分布)


🧰 十、进阶技巧

1. 动态模糊匹配阈值
代码语言:javascript
代码运行次数:0
运行
复制
SET pg_trgm.similarity_threshold = 0.4;

提高阈值 → 匹配更严格; 降低阈值 → 匹配更宽松。

2. 组合查询(混合搜索)
代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM users
WHERE name % '张明'
   OR name ILIKE '%张%'
ORDER BY similarity(name, '张明') DESC;

🎯 总结

项目

LIKE

pg_trgm

是否支持索引

❌ 否

✅ 是(GIN)

性能

支持相似度排序

❌ 否

✅ 是

安装复杂度

简单

需启用扩展

中文支持

✅(推荐 UTF8 编码)


✅ 实战建议

  • 模糊查询频繁的字段(如用户名、标题、商品名),强烈推荐使用 pg_trgm
  • 对搜索引擎类业务,可与 全文检索(tsvector) 结合;
  • 若需要跨字段、多语言搜索,再考虑引入 Elasticsearch

实用小工具

App Store 截图生成器应用图标生成器在线图片压缩Chrome插件-强制开启复制-护眼模式-网页乱码设置编码 乖猫记账,AI智能分类的最佳聊天记账App。 Elasticsearch可视化客户端工具

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🧠 一、pg_trgm 是什么?
  • 🧩 二、启用 pg_trgm 扩展
  • ⚙️ 三、创建测试表与数据
  • 🔍 四、使用 LIKE 进行模糊查询(传统方式)
  • ⚡ 五、使用 pg_trgm + GIN 索引提升性能
  • 🧪 六、相似度查询与排序
  • 🧩 七、常用函数与操作符汇总
  • 🔄 八、查询逻辑流程图(
  • 📈 九、性能对比实测(示意)
  • 🧰 十、进阶技巧
    • 1. 动态模糊匹配阈值
    • 2. 组合查询(混合搜索)
  • 🎯 总结
  • ✅ 实战建议
  • 实用小工具
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档