• 售前

  • 售后

热门帖子
入门百科

如何使用PostgreSQL进行中文全文检索

[复制链接]
六翼天使494 显示全部楼层 发表于 2021-8-14 14:52:43 |阅读模式 打印 上一主题 下一主题
目次


  • 开始

    • 安装
    • 插件
    • 启动

  • 配置

    • Host权限
    • 服务器配置

  • 分词

    • SCWS
    • zhpaser
    • SQL

  • 优化

    • 添加自定义辞书
    • 扩展

  • 总结

开始


安装

首先是安装 PgSQL,这里我使用的是 PgSQL 9.6,PgSQL 10 也刚发布了,有爱好的可以尝下鲜。
PgSQL 的安装可以说非常复杂了,除了要安装 Server 和 Client 外,还须要安装 devel 包。为了实现空间索引功能,我们还要安装最重要的 PostGIS 插件,此插件须要很多依赖,本技艺动安装非常复杂而且很大概堕落。
推荐自动化方式安装,Yum 肯定要配合 epel 如许的 Yum 源,保障能将依赖一扫而空。当然最好的照旧使用 docker 来运行,找个镜像就行了。

插件

由于 PgSQL 的很多功能都由插件实现,以是还要安装一些常用的插件,如:
  1. <span style="background-color: initial;">postgis_topology(管理面、边、点等拓扑对象)</span>
  2. pgrouting(路径规划)
  3. postgis_sfcgal(实现3D相关算法)
  4. fuzzystrmatch(字符串相似度计算)
  5. address_standardizer/address_standardizer_data_us(地址标准化)
  6. pg_trgm(分词索引)
复制代码
这些插件在安装目次 /path/extensions 下编译完毕后,在数据库中使用前要先使用 create extension xxx 启用。

启动

1.切换到非 root 用户。(PgSQL 在安装完毕后会创建一个名为 postgres 的超等用户,我们可以使用这个超等用户来操纵 PgSQL,后期建议重新创建一个普通用户用来管理数据);
2.切换到 /installPath/bin/ 目次下,PgSQL 在此目次下提供了很多命令,如 createdb、createuser、dropdb、pg_dump 等;
3.使用 createdb 命令初始化一个文件夹 dir_db (此目次不能已存在)存放数据库物理数据,使用 -E UTF8 参数指定数据库字符集为 utf-8;
4.使用 pg_ctl -D dir_db 指定数据库启动背景服务;
5.使用 psql -d db 在命令行登陆 PgSQL;

配置

安装完毕后还要配置一些比力根本的参数才气正常使用。

Host权限

PgSQL须要在 pg_hba.conf 文件中配置数据库 Host 权限,才气被其他机器访问。
  1. <span style="background-color: initial;"># TYPE  DATABASE        USER            ADDRESS                 METHOD</span>
  2. local   all             all                                     trust
  3. host    all             all             127.0.0.1/32            md5
  4. host    all             all             172.16.0.1/16            md5
复制代码
文件中注释部分对这几个字段介绍得比力具体, 我们很大概须要添加 host(IP) 访问项, ADDRESS 是普通的网段表示法,METHOD 推荐使用 md5,表示使用 md5 加密传输暗码。

服务器配置

服务器配置在 postgresql.conf中,修改配置后须要 使用 pg_ctl restart -D dir_db 命令重启数据库;
别的,我们也可以在登陆数据库后修改配置项:使用 SELECT * FROM pg_settings WHERE name = 'config'; 查询当前配置项,再使用 UPDATE 语句更新配置。但有些配置如内存分配计谋是只在当前 session 见效的,全局见效须要在配置文件中修改,再重启服务器。
我们可以修改配置并用客户端验证 SQL 语句的优化,使用 \timing on 开启查询计时,使用 EXPLAIN ANALYSE 语句 分析查询语句服从。 下面介绍两个已实践过的配置参数:
       
  • shared_buffers:用于指定共享内存缓冲区所占用的内存量。它应该富足大来存储常使用的查询效果,以减少物理I/O。但它也不能太大,以避免体系 内存swap 的发生, 一样平常设置为体系内存的 20%。   
  • work_mem:一个毗连的工作内存,在查询效果数据量较大时,此值如果较小的话,会导致大量体系 I/O,导致查询速度急剧降落,如果你的 explain 语句内 buffer 部分 read数值过大,则表示工作内存不敷,须要调整加此参数。但此值也不能太大,须要包管 work_mem * max_connections + shared_buffers + 体系内存 < RAM,否则同样大概会导致体系 内存swap。
如许,PgSQL 就能作为一个正常的关系型数据使用了。

分词

全文索引的实现要靠 PgSQL 的 gin 索引。分词功能 PgSQL 内置了英文、西班牙文等,但中文分词须要借助开源插件 zhparser;

SCWS

要使用 zhparser,我们首先要安装 SCWS 分词库,SCWS 是 Simple Chinese Word Segmentation 的首字母缩写(即:浅易中文分词体系),其 GitHub 项目地点为 hightman-scws,我们下载之后可以直接安装。
安装完后,就可以在命令行中使用 scws 命令举行测试分词了, 其参数重要有:
       
  • -c utf8 指定字符集   
  • -d dict 指定字典 可以是 xdb 或 txt 格式   
  • -M 复合分词的级别, 1~15,按位异或的 1|2|4|8 依次表示 短词|二元|重要字|全部字,默认不复合分词,这个参数可以帮助调整到最想要的分词效果。

zhpaser

1.下载 zhparser 源码 git clone https:github.com/amutu/zhparser.git;
2.安装前须要先配置情况变量:export PATH=$PATH:/path/to/pgsql;
3.make && make install编译 zhparser;
4.登陆 PgSQL 使用 CREATE EXTENSION zhparser; 启用插件;
5.添加分词配置
  1. CREATE TEXT SEARCH CONFIGURATION parser_name (PARSER = zhparser); // 添加配置
  2. ALTER TEXT SEARCH CONFIGURATION parser_name ADD MAPPING FOR n,v,a,i,e,l,j WITH simple; // 设置分词规则 (n 名词 v 动词等,详情阅读下面的文档)
复制代码
6.给某一列的分词效果添加 gin 索引 create index idx_name on table using gin(to_tsvector('parser_name', field));
7.在命令行中使用上一节中介绍的 scws 命令测试分词配置,如我认为复合等级为 7 时分词效果最好,则我在 postgresql.conf添加配置
  1. <span style="background-color: initial;">zhparser.multi_short = true #短词复合: 1</span>
  2. zhparser.multi_duality = true  #散字二元复合: 2
  3. zhparser.multi_zmain = true  #重要单字复合: 4
  4. zhparser.multi_zall = false  #全部单字复合: 8
复制代码
SQL

查询中我们可以使用最简朴的 SELECT * FROM table WHERE to_tsvector('parser_name', field) @@ 'word' 来查询 field 字段分词中带有 word 一词的数据;
使用 to_tsquery() 方法将句子解析成各个词的组合向量,如 国家大剧院 的返回效果为 '国家' & '大剧院' & '大剧' & '剧院' ,当然我们也可以使用 & | 符号拼接自己须要的向量;在查询 长句 时,可以使用 SELECT * FROM table WHERE to_tsvector('parser_name', field) @@ to_tsquery('parser_name','words');
偶然候我们想像 MySQL 的 SQL_CALC_FOUND_ROWS 语句一样同步返回效果条数,则可以使用 SELECT COUNT(*) OVER() AS score FROM table WHERE ...,PgSQL 会在每一行数据添加 score 字段存储查询到的总效果条数;
到这里,普通的全文检索需求已经实现了。

优化

我们接着对分词效果和服从举行优化:
存储分词效果
我们可以使用一个字段来存储分词向量,并在此字段上创建索引来更优地使用分词索引:
  1. ALTER TABLE table ADD COLUMN tsv_column tsvector;           // 添加一个分词字段
  2. UPDATE table SET tsv_column = to_tsvector('parser_name', coalesce(field,''));   // 将字段的分词向量更新到新字段中
  3. CREATE INDEX idx_gin_zhcn ON table USING GIN(tsv_column);   // 在新字段上创建索引
  4. CREATE TRIGGER trigger_name BEFORE INSERT OR UPDATE  ON table FOR EACH ROW EXECUTE PROCEDURE
  5. tsvector_update_trigger(tsv_column, 'parser_name', field); // 创建一个更新分词触发器
复制代码
如许,再举行查询时就可以直接使用 SELECT * FROM table WHERE tsv_column @@ 'keyword' 了。
这里须要注意,这时候在往表内插入数据的时候,大概会报错,提示指定 parser_name 的 schema, 这时候可以使用 \dF 命令查看全部 text search configuration 的参数:
  1. <span style="background-color: initial;">               List of text search configurations</span>
  2.    Schema   |    Name    |              Description
  3. ------------+------------+---------------------------------------
  4.  pg_catalog | english    | configuration for english language
  5.  public     | myparser   |
复制代码
注意 schema 参数,在创建 trigger 时须要指定 schema, 如上面,就须要使用 public.myparser。

添加自定义辞书

我们可以在网上下载 xdb 格式的词库来替换默认辞书,词库放在 share/tsearch_data/ 文件夹下才气被 PgSQL 读取到,默认使用的词库是 dict.utf8.xdb。要使用自定义词库,可以将词库放在词库文件夹后,在 postgresql.conf 配置 zhparser.extra_dict="mydict.xdb" 参数;
当我们只有 txt 的词库,想把这个词库作为默认词库该怎么办呢?使用 scws 带的
  1. scwe-gen-dict
复制代码
工具或网上找的脚本天生 xdb 后放入词库文件夹后,在 PgSQL 中分词不绝报错,读取词库文件失败。我颠末多次实行,总结出了一套制作一个辞书文件的方法:
1.准备词库源文件 mydict.txt:词库文件的内容每一行的格式为词 TF IDF 词性,词是必须的,而 TF 词频(Term Frequency)、IDF 反文档频率(Inverse Document Frequency) 和 词性 都是可选的,除非确定自己的辞书资料是对的且符合 scws 的配置,否则最好照旧留空,让 scws 自已确定;
2.在 postgresql.conf 中设置 zhparser.extra_dicts = "mydict.txt" 同时设置 zhparser.dict_in_memory = true;
3.命令行进入 PgSQL,实行一条分词语句 select to_tsquery('parser', '随便一个词') ,分词会极慢,请耐心(请包管此时只有一个分词语句在实行);
4.分词乐成后,在/tmp/目次下找到天生的 scws-xxxx.xdb 替换掉 share/tsearch_data/dict.utf8.xdb;
5.删除刚加入的 extra_dicts dict_in_memory 配置,重启服务器。

扩展

由于查询的是 POI 的名称,一样平常较短,且很多词并无语义,又思量到用户的输入风俗,一样平常会输入 POI 名称的前几个字符,而且 scws 的分词准确率也不能达到100%,于是我添加了名称的前缀查询来进步查询的准确率,纵然用 B树索引 实现 LIKE '关键词%' 的查询。这里需
这里要注意的是,创建索引时要根据字段范例配置 操纵符类,否则索引大概会不见效,如在 字段范例为 varchar 的字段上创建索引须要使用语句CREATE INDEX idx_name ON table(COLUMN varchar_pattern_ops),这里的 varcharpatternops 就是操纵符类。
自此,一个精良的全文检索体系就完成了。

总结

简朴的数据迁移并不是终点,后续要做的尚有很多,如整个体系的数据同步、查询服从优化、查询功能优化(添加拼音搜刮、模糊搜刮)等。特别是查询服从,不知道是不是我配置有问题,完全达不到那种 E级毫秒 的速度,1kw 的数据服从在举行大效果返回时就大幅降落(200ms),只好老诚实实地提前举行了分表,目前百万级查询速度在 20ms 以内,优化尚有一段路要走。
不外这次倒是对 技能的“生态”有了个更深的相识,这方面 PgSQL 确实和 MySQL 差远了,使用 MySQL 时再奇葩的问题都能在网上快速找到答案,而 PgSQL 就尴尬了,入门级的问题搜刮 stackoverflow 来往返回就那么几个对不上的答复。固然也有阿里的“德哥”一样的大神在辛劳布道,但用户的数目才是根本。不外,随着 PgSQL 越来越完善,使用它的人肯定会越来越多的,我这篇文章也算是为 PgSQL 加温了吧,哈哈~希望能帮到厥后的使用者。
以上就是怎样使用PostgreSQL举行中文全文检索的具体内容,更多关于使用PostgreSQL举行中文全文检索的资料请关注脚本之家别的干系文章!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作