2-5.全文索引与并行查询

全文索引与并行查询

全文索引

介绍

PostgreSQL 内置了全文检索功能,但默认仅支持英文检索。

可通过配置插件(如 zhparser)实现对中文的全文检索。

全文检索初步使用

PostgreSQL 将长文本分解为许多 token 的集合,称为 tsvector,代表文档内容。检索实际上是在 token 集合中进行的。

示例
sql 复制代码
-- 将文本转为 tsvector
SELECT 'we love postgresql database'::tsvector;
-- 使用函数分词
SELECT to_tsvector('we love postgresql database');

检索条件类型为 tsquery,是由简单逻辑运算符组成的字符串。

sql 复制代码
SELECT 'postgresql & love'::tsquery;
SELECT to_tsquery('postgresql & love');

全文检索使用 tsvectortsquery 进行匹配,运算符为 @@

sql 复制代码
SELECT 'we love postgresql database'::tsvector @@ 'postgresql & love'::tsquery; -- true
SELECT 'we love postgresql database'::tsvector @@ 'mysql | love'::tsquery;      -- true
SELECT 'we love postgresql database'::tsvector @@ 'mysql & love'::tsquery;      -- false

使用全文检索实际案例

建表并插入数据
sql 复制代码
CREATE TABLE myblog (
    id INT PRIMARY KEY,
    content TEXT,
    content_tsv TSVECTOR
);

-- 插入 100 万条记录
INSERT INTO myblog(id, content)
SELECT seq, 'PostgresQL' || seq || ' MySQL' || (seq + 10)
FROM generate_series(1, 1000000) AS seq;

-- 分词处理
UPDATE myblog SET content_tsv = to_tsvector(content);
查询示例
sql 复制代码
-- 查询包含 "postgresql1323" 的记录
SELECT * FROM myblog WHERE content_tsv @@ 'postgresql1323'::tsquery;
EXPLAIN SELECT * FROM myblog WHERE content_tsv @@ 'postgresql1323'::tsquery;

此时会进行全表扫描,性能较差。

创建 GIN 索引加速
sql 复制代码
CREATE INDEX idx_myblog_content_tsv ON myblog USING GIN(content_tsv);

-- 再次查询
SELECT * FROM myblog WHERE content_tsv @@ 'postgresql1323'::tsquery;
EXPLAIN SELECT * FROM myblog WHERE content_tsv @@ 'postgresql1323'::tsquery;

使用 zhparser 做中文全文检索

安装依赖
  1. 安装 PostgreSQL 开发包(以 PostgreSQL 15 为例):

    bash 复制代码
    yum install postgresql15-devel
  2. 安装 scws(中文分词器):

    bash 复制代码
    wget -q http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2
    tar xvf scws-1.2.3.tar.bz2
    cd scws-1.2.3
    ./configure
    make
    make install
  3. 安装 zhparser 插件(需从 GitHub 下载编译)。

配置与使用
sql 复制代码
-- 创建扩展
CREATE EXTENSION zhparser;

-- 创建中文全文检索配置
CREATE TEXT SEARCH CONFIGURATION testzhcfg (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION testzhcfg
ADD MAPPING FOR n,v,a,i,e,l WITH simple;
  • n, v, a, i, e, l 表示不同的 Token 策略,启用了这些 Token Mapping。
  • 使用 \dfp+ zhparser 查看详细含义。
示例表与数据
sql 复制代码
CREATE TABLE myblog (
    id INT PRIMARY KEY,
    content TEXT,
    content_tsv TSVECTOR
);

INSERT INTO myblog(id, content) VALUES
(1, '中国南京市长江大桥'),
(2, '是一种特性非常齐全的自由软件的对象-关系型数据库管理系统'),
(3, '是以加州大学计算机系开发的POSTGRES'),
(4, '4.2版本为基础的对象关系型数据库管理系统'),
(5, 'PostgreSQL是一个功能非常强大的、源代码开放的客户/服务器关系型数据库管理系统(RDBMS)'),
(6, 'PostgreSQL是一个非常健壮的软件包,有很多在大型商业RDBMS中所具有的特性'),
(7, '包括事务、子选择、触发器、视图、外键引用完整性和复杂锁定功能'),
(8, '全球开发组今天宣布,世界上功能最为强大的开源数据库发布');

-- 使用 testzhcfg 配置分词
UPDATE myblog SET content_tsv = to_tsvector('testzhcfg', content);

-- 创建 GIN 索引
CREATE INDEX idx_myblog_content_tsv ON myblog USING GIN(content_tsv);
中文全文检索查询
sql 复制代码
-- 检索包含"南京市"的文档
SELECT * FROM myblog WHERE content_tsv @@ to_tsquery('testzhcfg', '南京市');

-- 中文检索中也可查询英文单词
SELECT id, content FROM myblog WHERE content_tsv @@ to_tsquery('testzhcfg', 'postgresql');

并行查询功能

并行查询利用多 CPU 和多核的能力,可显著缩短大数据量查询的处理时间。

并行查询相关配置参数

参数名 说明
dynamic_shared_memory_type 必须设置为非 none 值,用于进程间数据传递
max_worker_processes 整个数据库实例允许的最大后台工作进程数(默认 8)
max_parallel_workers 整个实例允许用于并行的后台工作进程数
max_parallel_workers_per_gather 单个并行操作允许的并行度(需小于 max_parallel_workers
min_parallel_table_scan_size 表大小小于此值时不走并行(默认 8MB)
min_parallel_index_scan_size 索引扫描大小小于此值时不走并行(默认 512KB)
成本估算参数
  • parallel_setup_cost:并行启动成本
  • parallel_tuple_cost:并行处理每行数据的成本

是否使用并行取决于 CBO(成本优化器)的计算结果。若非并行的成本低于并行成本,则不使用并行。

强制并行模式
sql 复制代码
SET force_parallel_mode = on;  -- 慎用于生产环境,一般用于测试

支持的并行操作

操作类型 说明
并行顺序扫描 全表扫描(sequential scan)
并行索引扫描 索引扫描(index scan)
并行 index-only 扫描 index only 扫描
并行 bitmap heap 扫描 bitmap heap 扫描
并行聚合 COUNT()SUM() 等聚合操作
Nested loop 并行 Nested loop 多表关联
Merge join 并行 Merge join 多表关联
Hash Join 并行 Hash Join 多表关联
并行 create index BTree 索引的并行创建
CREATE TABLE ... AS 支持并行执行

总结

功能 关键点
全文索引 内置英文检索,通过插件支持中文;使用 tsvector/tsquery 和 GIN 索引
zhparser 需安装 scws 分词器,配置 Token Mapping,支持中英文混合检索
并行查询 利用多核 CPU,需配置相关参数;CBO 决定是否并行;支持多种扫描与连接操作

相关推荐
曲幽7 小时前
我用了FastApiAdmin后,连夜把踩过的坑都整理出来了
redis·python·postgresql·vue3·fastapi·web·sqlalchemy·admin·fastapiadmin
Muscleheng11 小时前
Navicat连接postgresql时出现‘datlastsysoid does not exist‘报错
数据库·postgresql
Gauss松鼠会15 小时前
GaussDB(DWS) 日常维护命令
服务器·数据库·postgresql·性能优化·gaussdb·经验总结
IvorySQL17 小时前
开源共建分论坛圆桌讨论:如何真正融入 PostgreSQL 社区?
postgresql·开源·区块链
l1t17 小时前
DeepSeek总结的postgresql 数据分析师 vs width_bucket()
数据库·postgresql
l1t1 天前
DeepSeek总结的PostgreSQL 表访问方法
数据库·postgresql
星星也在雾里1 天前
PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控
数据库·postgresql
zhojiew2 天前
在本地PostgreSQL使用pgvector构建生成式 AI 应用的实践
数据库·人工智能·postgresql
snowfoootball2 天前
解决低版本navicat连接PostgreSQl的不兼容报错问题
数据库·postgresql
csdn小瓯2 天前
PostgreSQL迁移实战:从SQLite到生产级数据库的平滑演进
数据库·postgresql·sqlite