PostgreSQL教程FG281-PG全文检索实战:企业级搜索功能搭建
本文档风哥主要介绍PostgreSQL全文检索(Full-Text Search,简称FTS)的实战应用,包括全文检索的配置、索引、查询等内容。风哥教程参考PostgreSQL官方文档Full Text Search内容,适合企业级应用中需要实现高效搜索功能的场景。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 PostgreSQL全文检索的概念
PostgreSQL全文检索是一种用于在文本数据中进行高效搜索的功能,它允许用户通过关键词、短语或复杂查询来搜索文本内容。全文检索的主要特点:
- 支持自然语言搜索
- 支持词干提取和词形还原
- 支持停用词过滤
- 支持排名和相关性评分
- 支持复杂的查询语法
- 支持多种语言
相比传统的LIKE查询,全文检索提供了更高效、更准确的搜索能力,特别适合处理大量文本数据的搜索需求。
1.2 全文检索架构
PostgreSQL全文检索的架构包括以下组件:
1. 文档(Document):要搜索的文本数据
2. 分词器(Tokenizer):将文本分解为单词(tokens)
3. 词干提取器(Stemmer):将单词还原为词干形式
4. 停用词过滤器(Stopword Filter):过滤掉常见的无意义词
5. 全文检索向量(tsvector):存储处理后的文本数据
6. 全文检索查询(tsquery):表示搜索条件
7. 索引:加速全文检索查询
# 全文检索流程
1. 文本处理:将原始文本转换为tsvector
2. 索引创建:为tsvector创建GIN或GiST索引
3. 查询处理:将用户查询转换为tsquery
4. 匹配计算:计算tsvector与tsquery的匹配度
5. 结果排序:根据相关性评分排序结果
# 数据类型
– tsvector:存储全文检索向量
– tsquery:存储全文检索查询
1.3 全文检索适用场景
PostgreSQL全文检索适用于以下场景:
1. 内容管理系统:如博客、新闻网站的文章搜索
2. 电子商务平台:产品描述和评论搜索
3. 文档管理系统:文档内容搜索
4. 知识库:问答和文档搜索
5. 社交媒体:用户帖子和评论搜索
6. 日志分析:系统日志和应用日志搜索
7. 站内搜索:网站内部内容搜索
# 不适用场景
1. 精确匹配:如ID、电话号码等精确值搜索
2. 范围查询:如日期、价格等范围搜索
3. 结构化数据查询:如按类别、标签等过滤
4. 复杂的关系查询:需要多表关联的查询
Part02-生产环境规划与建议
2.1 全文检索规划
在实施全文检索前,需要进行详细的规划:
1. 数据量评估:估算需要索引的文本数据量
2. 搜索需求:分析搜索的频率、复杂度和响应时间要求
3. 语言支持:确定需要支持的语言
4. 索引策略:选择合适的索引类型和配置
5. 存储需求:估算索引的存储需求
6. 性能目标:设定搜索响应时间和并发处理能力
# 数据量估算
– 文档数量:从几千到几百万
– 每个文档的平均大小:从几KB到几MB
– 总文本数据量:从几GB到几十GB
# 搜索需求分析
– 搜索频率:每秒搜索次数
– 搜索复杂度:简单关键词搜索还是复杂短语搜索
– 响应时间要求:毫秒级还是秒级
– 并发用户数:同时进行搜索的用户数量
2.2 语言支持与配置
PostgreSQL支持多种语言的全文检索,需要根据实际需求配置语言支持:
– 英语(english)
– 中文(chinese)
– 日语(japanese)
– 德语(german)
– 法语(french)
– 西班牙语(spanish)
– 俄语(russian)
– 等等
# 语言配置
– 词干提取器:不同语言有不同的词干提取算法
– 停用词列表:不同语言有不同的停用词
– 分词规则:不同语言有不同的分词规则
# 中文支持
– PostgreSQL内置的中文支持有限
– 推荐使用pg_jieba扩展提供更好的中文分词支持
– 或者使用zhparser扩展
# 自定义语言配置
– 可以创建自定义的文本搜索配置
– 可以自定义词干提取器和停用词列表
2.3 性能考虑因素
全文检索性能考虑因素:
- 索引类型:对于全文检索,推荐使用GIN索引,它在全文检索查询中性能更好
- 索引维护:定期维护索引,确保索引的有效性
- 内存配置:增加shared_buffers以提高索引缓存效率
- 存储设备:使用SSD提高索引访问速度
- 查询优化:优化查询语句,避免复杂的全文检索查询
Part03-生产环境项目实施方案
3.1 全文检索配置
3.1.1 文本搜索配置
SELECT cfgname FROM pg_ts_config;
# 查看默认配置
SHOW default_text_search_config;
# 设置默认配置
SET default_text_search_config = ‘english’;
# 创建自定义文本搜索配置
CREATE TEXT SEARCH CONFIGURATION my_config (
COPY = english
);
# 修改文本搜索配置
ALTER TEXT SEARCH CONFIGURATION my_config
ADD MAPPING FOR asciiword, asciihword, hword_asciipart
WITH simple;
# 查看文本搜索配置的详细信息
SELECT * FROM pg_ts_config WHERE cfgname = ‘english’;
# 查看文本搜索词典
SELECT * FROM pg_ts_dict WHERE dictname LIKE ‘%english%’;
3.1.2 中文分词配置
— 编译安装
$ git clone https://github.com/jaiminpan/pg_jieba.git
$ cd pg_jieba
$ make && make install
— 在PostgreSQL中创建扩展
CREATE EXTENSION pg_jieba;
# 创建中文文本搜索配置
CREATE TEXT SEARCH CONFIGURATION chinese_jieba (
COPY = english
);
# 修改配置使用jieba分词
ALTER TEXT SEARCH CONFIGURATION chinese_jieba
ALTER MAPPING FOR hword, hword_part, word
WITH jieba;
# 测试中文分词
SELECT to_tsvector(‘chinese_jieba’, ‘ PostgreSQL全文检索实战’);
# 输出示例
to_tsvector
——————————–
‘postgresql’:1 ‘实战’:4 ‘检索’:3 ‘全文’:2
(1 row)
3.2 全文检索索引
3.2.1 创建全文检索向量
CREATE TABLE fgedu_articles (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
# 添加全文检索向量列
ALTER TABLE fgedu_articles ADD COLUMN search_vector tsvector;
# 更新全文检索向量
UPDATE fgedu_articles
SET search_vector = to_tsvector(‘english’, title || ‘ ‘ || content);
# 创建GIN索引
CREATE INDEX idx_fgedu_articles_search_vector ON fgedu_articles USING GIN (search_vector);
# 创建触发器自动更新全文检索向量
CREATE OR REPLACE FUNCTION fgedu_articles_search_vector_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.search_vector := to_tsvector(‘english’, NEW.title || ‘ ‘ || NEW.content);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER fgedu_articles_search_vector_update
BEFORE INSERT OR UPDATE ON fgedu_articles
FOR EACH ROW EXECUTE FUNCTION fgedu_articles_search_vector_update();
# 插入测试数据
INSERT INTO fgedu_articles (title, content)
VALUES
(‘PostgreSQL全文检索’, ‘PostgreSQL全文检索是一种强大的搜索功能,支持自然语言搜索。’),
(‘PostgreSQL性能优化’, ‘PostgreSQL性能优化包括索引优化、查询优化等多个方面。’),
(‘PostgreSQL备份与恢复’, ‘PostgreSQL备份与恢复是数据库管理的重要组成部分。’);
# 查看全文检索向量
SELECT id, title, search_vector FROM fgedu_articles;
3.2.2 索引类型选择
# GIN索引
– 优点:在全文检索查询中性能更好,支持快速搜索
– 缺点:索引构建较慢,占用空间较大
– 适用场景:搜索频繁,数据更新不频繁的场景
# GiST索引
– 优点:索引构建较快,占用空间较小
– 缺点:搜索性能不如GIN索引
– 适用场景:数据更新频繁,搜索性能要求不高的场景
# 创建GIN索引
CREATE INDEX idx_fgedu_articles_search_vector ON fgedu_articles USING GIN (search_vector);
# 创建GiST索引
CREATE INDEX idx_fgedu_articles_search_vector_gist ON fgedu_articles USING GiST (search_vector);
# 部分索引
– 只为特定条件的行创建索引
CREATE INDEX idx_fgedu_articles_search_vector_active ON fgedu_articles USING GIN (search_vector)
WHERE status = ‘active’;
# 表达式索引
– 基于表达式创建索引
CREATE INDEX idx_fgedu_articles_search_vector_expr ON fgedu_articles USING GIN (
to_tsvector(‘english’, title || ‘ ‘ || content)
);
3.3 全文检索查询
3.3.1 基本查询
— 使用@@操作符
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’);
— 结果
id | title | content
—-+———————–+————————————————————–
1 | PostgreSQL全文检索 | PostgreSQL全文检索是一种强大的搜索功能,支持自然语言搜索。
2 | PostgreSQL性能优化 | PostgreSQL性能优化包括索引优化、查询优化等多个方面。
3 | PostgreSQL备份与恢复 | PostgreSQL备份与恢复是数据库管理的重要组成部分。
# 复杂查询
— 搜索多个关键词
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL & 性能’);
— 结果
id | title | content
—-+———————–+————————————————————–
2 | PostgreSQL性能优化 | PostgreSQL性能优化包括索引优化、查询优化等多个方面。
— 搜索短语
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘全文检索’);
— 结果
id | title | content
—-+———————–+————————————————————–
1 | PostgreSQL全文检索 | PostgreSQL全文检索是一种强大的搜索功能,支持自然语言搜索。
— 使用OR操作符
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘性能 | 备份’);
— 结果
id | title | content
—-+———————–+————————————————————–
2 | PostgreSQL性能优化 | PostgreSQL性能优化包括索引优化、查询优化等多个方面。
3 | PostgreSQL备份与恢复 | PostgreSQL备份与恢复是数据库管理的重要组成部分。
3.3.2 高级查询
— 使用ts_rank计算相关性
SELECT id, title, content, ts_rank(search_vector, to_tsquery(‘english’, ‘PostgreSQL’)) AS rank
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
ORDER BY rank DESC;
— 结果
id | title | content | rank
—-+———————–+————————————————————–+———-
1 | PostgreSQL全文检索 | PostgreSQL全文检索是一种强大的搜索功能,支持自然语言搜索。 | 0.0607927
2 | PostgreSQL性能优化 | PostgreSQL性能优化包括索引优化、查询优化等多个方面。 | 0.0607927
3 | PostgreSQL备份与恢复 | PostgreSQL备份与恢复是数据库管理的重要组成部分。 | 0.0607927
— 使用ts_rank_cd计算更复杂的相关性
SELECT id, title, content, ts_rank_cd(search_vector, to_tsquery(‘english’, ‘PostgreSQL’)) AS rank
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
ORDER BY rank DESC;
# 前缀搜索
— 使用:*进行前缀搜索
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘Postg:*’);
# 模糊搜索
— 使用phraseto_tsquery进行模糊搜索
SELECT id, title, content
FROM fgedu_articles
WHERE search_vector @@ phraseto_tsquery(‘english’, ‘PostgreSQL 搜索’);
# 权重设置
— 在创建tsvector时设置权重
UPDATE fgedu_articles
SET search_vector =
setweight(to_tsvector(‘english’, title), ‘A’) ||
setweight(to_tsvector(‘english’, content), ‘B’);
— 搜索时考虑权重
SELECT id, title, content, ts_rank(search_vector, to_tsquery(‘english’, ‘PostgreSQL’)) AS rank
FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
ORDER BY rank DESC;
Part04-生产案例与实战讲解
4.1 全文检索实战案例
4.1.1 内容管理系统搜索
# 1. 数据库设计
CREATE TABLE fgedu_cms_articles (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
author VARCHAR(100) NOT NULL,
category VARCHAR(100) NOT NULL,
tags VARCHAR(255),
status VARCHAR(20) DEFAULT ‘published’,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
search_vector tsvector
);
# 2. 创建索引
CREATE INDEX idx_fgedu_cms_articles_search_vector ON fgedu_cms_articles USING GIN (search_vector);
CREATE INDEX idx_fgedu_cms_articles_category ON fgedu_cms_articles (category);
CREATE INDEX idx_fgedu_cms_articles_status ON fgedu_cms_articles (status);
# 3. 创建触发器
CREATE OR REPLACE FUNCTION fgedu_cms_articles_search_vector_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.search_vector :=
setweight(to_tsvector(‘english’, NEW.title), ‘A’) ||
setweight(to_tsvector(‘english’, NEW.content), ‘B’) ||
setweight(to_tsvector(‘english’, NEW.author), ‘C’) ||
setweight(to_tsvector(‘english’, NEW.tags), ‘D’);
NEW.updated_at := CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER fgedu_cms_articles_search_vector_update
BEFORE INSERT OR UPDATE ON fgedu_cms_articles
FOR EACH ROW EXECUTE FUNCTION fgedu_cms_articles_search_vector_update();
# 4. 插入测试数据
INSERT INTO fgedu_cms_articles (title, content, author, category, tags)
VALUES
(‘PostgreSQL全文检索实战’, ‘本文介绍PostgreSQL全文检索的实战应用…’, ‘风哥’, ‘数据库’, ‘PostgreSQL,全文检索,数据库’),
(‘PostgreSQL性能优化技巧’, ‘本文介绍PostgreSQL性能优化的各种技巧…’, ‘风哥’, ‘数据库’, ‘PostgreSQL,性能优化,数据库’),
(‘PostgreSQL备份与恢复策略’, ‘本文介绍PostgreSQL备份与恢复的最佳策略…’, ‘风哥’, ‘数据库’, ‘PostgreSQL,备份,恢复’),
(‘MySQL与PostgreSQL对比’, ‘本文对比MySQL与PostgreSQL的优缺点…’, ‘风哥’, ‘数据库’, ‘MySQL,PostgreSQL,对比’),
(‘PostgreSQL高可用架构’, ‘本文介绍PostgreSQL高可用架构的设计…’, ‘风哥’, ‘数据库’, ‘PostgreSQL,高可用,架构’);
# 5. 搜索示例
— 基本搜索
SELECT id, title, author, category
FROM fgedu_cms_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
AND status = ‘published’
ORDER BY created_at DESC;
— 高级搜索(带排名)
SELECT id, title, author, category,
ts_rank(search_vector, to_tsquery(‘english’, ‘PostgreSQL & 性能’)) AS rank
FROM fgedu_cms_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL & 性能’)
AND status = ‘published’
ORDER BY rank DESC, created_at DESC;
— 按类别搜索
SELECT id, title, author, category
FROM fgedu_cms_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘备份’)
AND category = ‘数据库’
AND status = ‘published’
ORDER BY created_at DESC;
— 前缀搜索
SELECT id, title, author, category
FROM fgedu_cms_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘Postg:*’)
AND status = ‘published’
ORDER BY created_at DESC;
4.1.2 电子商务平台搜索
# 1. 数据库设计
CREATE TABLE fgedu_products (
id SERIAL PRIMARY KEY,
sku VARCHAR(50) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category VARCHAR(100) NOT NULL,
brand VARCHAR(100) NOT NULL,
tags VARCHAR(255),
stock INTEGER NOT NULL,
status VARCHAR(20) DEFAULT ‘active’,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
search_vector tsvector
);
# 2. 创建索引
CREATE INDEX idx_fgedu_products_search_vector ON fgedu_products USING GIN (search_vector);
CREATE INDEX idx_fgedu_products_category ON fgedu_products (category);
CREATE INDEX idx_fgedu_products_brand ON fgedu_products (brand);
CREATE INDEX idx_fgedu_products_price ON fgedu_products (price);
CREATE INDEX idx_fgedu_products_status ON fgedu_products (status);
# 3. 创建触发器
CREATE OR REPLACE FUNCTION fgedu_products_search_vector_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.search_vector :=
setweight(to_tsvector(‘english’, NEW.name), ‘A’) ||
setweight(to_tsvector(‘english’, NEW.description), ‘B’) ||
setweight(to_tsvector(‘english’, NEW.brand), ‘C’) ||
setweight(to_tsvector(‘english’, NEW.tags), ‘D’);
NEW.updated_at := CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER fgedu_products_search_vector_update
BEFORE INSERT OR UPDATE ON fgedu_products
FOR EACH ROW EXECUTE FUNCTION fgedu_products_search_vector_update();
# 4. 插入测试数据
INSERT INTO fgedu_products (sku, name, description, price, category, brand, tags, stock)
VALUES
(‘PROD001’, ‘Smartphone’, ‘Latest smartphone with advanced features…’, 999.99, ‘Electronics’, ‘Apple’, ‘smartphone,electronics,Apple’, 100),
(‘PROD002’, ‘Laptop’, ‘High performance laptop for professionals…’, 1299.99, ‘Electronics’, ‘Dell’, ‘laptop,electronics,Dell’, 50),
(‘PROD003’, ‘T-Shirt’, ‘Comfortable cotton t-shirt…’, 29.99, ‘Clothing’, ‘Nike’, ‘t-shirt,clothing,Nike’, 200),
(‘PROD004’, ‘Running Shoes’, ‘Lightweight running shoes for athletes…’, 129.99, ‘Shoes’, ‘Nike’, ‘running shoes,sports,Nike’, 150),
(‘PROD005’, ‘Smartwatch’, ‘Fitness tracking smartwatch…’, 299.99, ‘Electronics’, ‘Apple’, ‘smartwatch,fitness,Apple’, 75);
# 5. 搜索示例
— 基本产品搜索
SELECT id, sku, name, price, brand
FROM fgedu_products
WHERE search_vector @@ to_tsquery(‘english’, ‘smartphone’)
AND status = ‘active’
AND stock > 0
ORDER BY price ASC;
— 高级搜索(带排名和过滤)
SELECT id, sku, name, price, brand,
ts_rank(search_vector, to_tsquery(‘english’, ‘Apple & smart’)) AS rank
FROM fgedu_products
WHERE search_vector @@ to_tsquery(‘english’, ‘Apple & smart’)
AND status = ‘active’
AND stock > 0
AND price < 500
ORDER BY rank DESC, price ASC;
-- 按类别搜索
SELECT id, sku, name, price, brand
FROM fgedu_products
WHERE search_vector @@ to_tsquery('english', 'running')
AND category = 'Shoes'
AND status = 'active'
AND stock > 0
ORDER BY price ASC;
— 前缀搜索
SELECT id, sku, name, price, brand
FROM fgedu_products
WHERE search_vector @@ to_tsquery(‘english’, ‘lap:*’)
AND status = ‘active’
AND stock > 0
ORDER BY price ASC;
4.2 全文检索性能优化
4.2.1 索引优化
# 1. 选择合适的索引类型
— GIN索引(推荐)
CREATE INDEX idx_fgedu_articles_search_vector ON fgedu_articles USING GIN (search_vector);
— GiST索引(适用于更新频繁的场景)
CREATE INDEX idx_fgedu_articles_search_vector_gist ON fgedu_articles USING GiST (search_vector);
# 2. 索引维护
— 定期重建索引
REINDEX INDEX idx_fgedu_articles_search_vector;
— 分析表以更新统计信息
ANALYZE fgedu_articles;
# 3. 部分索引
— 只为活跃数据创建索引
CREATE INDEX idx_fgedu_articles_search_vector_active ON fgedu_articles USING GIN (search_vector)
WHERE status = ‘active’;
# 4. 复合索引
— 结合其他条件创建复合索引
CREATE INDEX idx_fgedu_articles_category_search ON fgedu_articles (category) INCLUDE (search_vector);
# 5. 表达式索引
— 直接基于表达式创建索引
CREATE INDEX idx_fgedu_articles_search_expr ON fgedu_articles USING GIN (
to_tsvector(‘english’, title || ‘ ‘ || content)
);
4.2.2 查询优化
# 1. 简化查询
— 避免复杂的查询表达式
— 好的查询
SELECT * FROM fgedu_articles WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’);
— 不好的查询
SELECT * FROM fgedu_articles WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL & (performance | optimization) & !backup’);
# 2. 使用适当的查询操作符
— 使用&(AND)、|(OR)、!(NOT)操作符
— 合理组合查询条件
# 3. 限制结果集
— 使用LIMIT限制返回结果
SELECT * FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
LIMIT 10;
# 4. 利用排名进行排序
— 使用ts_rank进行相关性排序
SELECT * FROM fgedu_articles
WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’)
ORDER BY ts_rank(search_vector, to_tsquery(‘english’, ‘PostgreSQL’)) DESC
LIMIT 10;
# 5. 避免全表扫描
— 确保查询使用索引
— 检查执行计划
EXPLAIN ANALYZE SELECT * FROM fgedu_articles WHERE search_vector @@ to_tsquery(‘english’, ‘PostgreSQL’);
# 6. 使用物化视图
— 对于频繁的复杂查询,使用物化视图
CREATE MATERIALIZED VIEW fgedu_articles_search AS
SELECT id, title, content, search_vector
FROM fgedu_articles
WHERE status = ‘active’;
— 创建索引
CREATE INDEX idx_fgedu_articles_search_mv ON fgedu_articles_search USING GIN (search_vector);
— 定期刷新物化视图
REFRESH MATERIALIZED VIEW fgedu_articles_search;
4.2.3 存储优化
# 1. 压缩存储
— PostgreSQL会自动压缩tsvector数据
— 可以通过pg_column_size查看存储大小
SELECT id, title, pg_column_size(search_vector) AS size
FROM fgedu_articles
ORDER BY size DESC;
# 2. 分区表
— 对于大量数据,使用分区表
CREATE TABLE fgedu_articles_partitioned (
id SERIAL,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
search_vector tsvector,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
PARTITION BY RANGE (created_at);
— 创建分区
CREATE TABLE fgedu_articles_2026_q1 PARTITION OF fgedu_articles_partitioned
FOR VALUES FROM (‘2026-01-01’) TO (‘2026-04-01’);
CREATE TABLE fgedu_articles_2026_q2 PARTITION OF fgedu_articles_partitioned
FOR VALUES FROM (‘2026-04-01’) TO (‘2026-07-01’);
— 在每个分区上创建索引
CREATE INDEX idx_fgedu_articles_2026_q1_search ON fgedu_articles_2026_q1 USING GIN (search_vector);
CREATE INDEX idx_fgedu_articles_2026_q2_search ON fgedu_articles_2026_q2 USING GIN (search_vector);
# 3. 批量更新
— 对于大量数据的更新,使用批量操作
— 避免单行更新的开销
UPDATE fgedu_articles
SET search_vector = to_tsvector(‘english’, title || ‘ ‘ || content)
WHERE id BETWEEN 1 AND 1000;
# 4. 减少不必要的字段
— 只存储必要的文本数据
— 避免在search_vector中包含无关内容
4.3 全文检索常见问题处理
4.3.1 常见错误及解决方法
# 问题:搜索结果与预期不符
# 解决方法:
– 检查文本搜索配置是否正确
– 检查分词是否正确
– 调整权重设置
– 检查停用词配置
# 2. 搜索性能慢
# 问题:搜索查询执行缓慢
# 解决方法:
– 创建适当的索引(GIN索引)
– 优化查询语句
– 增加内存配置
– 使用物化视图
# 3. 索引膨胀
# 问题:全文检索索引占用空间过大
# 解决方法:
– 定期重建索引
– 使用部分索引
– 优化tsvector的大小
# 4. 中文分词问题
# 问题:中文搜索效果不佳
# 解决方法:
– 安装pg_jieba或zhparser扩展
– 配置中文文本搜索配置
– 调整分词参数
# 5. 内存使用过高
# 问题:全文检索查询使用大量内存
# 解决方法:
– 限制结果集大小
– 优化查询语句
– 调整work_mem参数
– 使用游标处理大结果集
4.3.2 全文检索监控
# 1. 监控索引大小
SELECT indexrelid::regclass AS index_name,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_fgedu_indexes
WHERE indexrelid::regclass::text LIKE ‘%search_vector%’
ORDER BY pg_relation_size(indexrelid) DESC;
# 2. 监控查询性能
SELECT query, calls, total_exec_time, mean_exec_time
FROM pg_stat_statements
WHERE query LIKE ‘%@@%’ OR query LIKE ‘%to_tsquery%’
ORDER BY total_exec_time DESC
LIMIT 10;
# 3. 监控索引使用情况
SELECT indexrelid::regclass AS index_name,
relid::regclass AS table_name,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_fgedu_indexes
JOIN pg_stat_fgedu_tables ON pg_stat_fgedu_indexes.relid = pg_stat_fgedu_tables.relid
WHERE indexrelid::regclass::text LIKE ‘%search_vector%’
ORDER BY idx_scan DESC;
# 4. 监控tsvector大小
SELECT avg(pg_column_size(search_vector)) AS avg_size,
max(pg_column_size(search_vector)) AS max_size,
min(pg_column_size(search_vector)) AS min_size
FROM fgedu_articles;
# 5. 监控分词性能
— 使用EXPLAIN分析分词性能
EXPLAIN ANALYZE SELECT to_tsvector(‘english’, title || ‘ ‘ || content) FROM fgedu_articles;
Part05-风哥经验总结与分享
5.1 全文检索最佳实践
PostgreSQL全文检索最佳实践:
- 选择合适的索引类型:对于全文检索,推荐使用GIN索引
- 合理配置文本搜索:根据语言和业务需求,选择或创建合适的文本搜索配置
- 使用触发器自动更新:使用触发器自动更新全文检索向量,确保数据一致性
- 设置适当的权重:为不同字段设置不同的权重,提高搜索结果的相关性
- 优化查询语句:简化查询表达式,使用适当的查询操作符
- 定期维护索引:定期重建索引,确保索引的有效性
- 监控性能:定期监控全文检索的性能,及时发现并解决问题
- 考虑中文分词:对于中文搜索,使用pg_jieba或zhparser扩展提高分词效果
5.2 全文检索实施检查清单
## 规划阶段
– [ ] 评估数据量和搜索需求
– [ ] 确定需要支持的语言
– [ ] 选择合适的文本搜索配置
– [ ] 规划索引策略
## 实施阶段
– [ ] 创建包含tsvector字段的表
– [ ] 创建GIN或GiST索引
– [ ] 实现触发器自动更新tsvector
– [ ] 测试搜索功能
## 优化阶段
– [ ] 分析查询执行计划
– [ ] 优化索引策略
– [ ] 调整权重设置
– [ ] 监控性能指标
## 维护阶段
– [ ] 定期重建索引
– [ ] 更新统计信息
– [ ] 监控索引大小
– [ ] 备份全文检索数据
## 扩展阶段
– [ ] 考虑使用pg_jieba等扩展
– [ ] 实现高级搜索功能
– [ ] 优化搜索结果排序
– [ ] 集成搜索建议功能
5.3 全文检索工具推荐
PostgreSQL全文检索相关工具推荐:
- pg_jieba:中文分词扩展,提供更好的中文全文检索支持
- zhparser:中文分词扩展,基于SCWS分词系统
- pg_trgm: trigram索引扩展,支持模糊搜索
- pg_bigm: bigram索引扩展,支持日文等语言的搜索
- Elasticsearch: 外部搜索引擎,与PostgreSQL集成提供更强大的搜索功能
- Solr: 外部搜索引擎,与PostgreSQL集成提供企业级搜索功能
- pgAdmin: 图形化工具,支持全文检索配置和管理
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
