【搜索引擎】 PostgreSQL 10 实时全文检索和分词、相似搜索、模糊匹配实现类似Google搜索自动提示
需求分析
要通过PostgreSQL实现类似Google搜索自动提示的功能,例如要实现一个查询海量数据中的商品名字,每次输入就提示用户各种相关搜索选项,例如淘宝、京东等电商查询
思路
这个功能可以用 PostgreSQL的实时全文检索和分词、相似搜索、前模糊匹配等特性实现。具体策略是,定义一个搜索提示的最大数量。首先通过前模糊匹配查询获取数据,如果未满最大数量,则进行全文检索分词查询补偿,如果全文检索补偿查询的数据未满最大提示数量,最后就加入相识查询的结果。当然这里是一个简单的思路,复杂的还得根据实际需求实现。
构造数据
新建一张商品表,插入一千万条数据,name就是商品名字。
create table goods(id int, name varchar);
insert into goods select generate_series(1,10000000),md5(random()::varchar);
一、前模糊匹配及优化
实现SQL,每次输入就作为前缀模糊查询:
select * from goods where name like '123%' ;
这个简单的前模糊匹配SQL,可以使用B-Tree来加速优化模糊查询。
未建立索引时查询"123%"的商品名字,执行计划显示耗时大约为575ms:
explain (analyze,verbose,timing,costs,buffers) select * from goods where name like '123%' ;
========================================
Gather (cost=1000.00..136516.59 rows=1000 width=37) (actual time=1.390..572.857 rows=2364 loops=1)
Output: id, name
Workers Planned: 2
Workers Launched: 2
Buffers: shared hit=83334
-> Parallel Seq Scan on public.goods (cost=0.00..135416.59 rows=417 width=37) (actual time=0.750..528.116 rows=788 loops=3)
Output: id, name
Filter: ((goods.name)::text ~~ '123%'::text)
Rows Removed by Filter: 3332545
Buffers: shared hit=83334
Worker 0: actual time=1.032..511.776 rows=676 loops=1
Buffers: shared hit=24201
Worker 1: actual time=0.145..511.737 rows=755 loops=1
Buffers: shared hit=26101
Planning time: 0.065 ms
Execution time: 573.157 ms
优化1,建立索引(lc_collate方式)
通过lc_collate方式建立索引、也就是B-Tree索引。
- lc_collate (string) 是指报告文本数据排序使用的区域
- lc_collate (string) 是指报告文本数据排序使用的区域
建立索引脚本如下
create index idx_c on goods(name collate "C");
执行计划显示耗时为10ms以内:
explain (analyze,verbose,timing,costs,buffers) select * from goods where name like '123%' collate "C";
优化2,建立索引(操作符类varchar_pattern_ops方式)
建立索引脚本如下
create index idx_varchar on goods(name varchar_pattern_ops);
执行计划显示耗时为5ms以内:
explain (analyze,verbose,timing,costs,buffers) select * from goods where name like '123%' collate "C";
======================================
Bitmap Heap Scan on public.goods (cost=86.60..7681.10 rows=1000 width=37) (actual time=0.740..4.628 rows=2364 loops=1)
Output: id, name
Filter: ((goods.name)::text ~~ '123%'::text)
Heap Blocks: exact=2330
Buffers: shared hit=2351
-> Bitmap Index Scan on idx_varchar (cost=0.00..86.35 rows=2179 width=0) (actual time=0.487..0.487 rows=2364 loops=1)
Index Cond: (((goods.name)::text ~>=~ '123'::text) AND ((goods.name)::text ~<~ '124'::text))
Buffers: shared hit=21
Planning time: 0.139 ms
Execution time: 4.891 ms
二、全文检索和分词(通过gin索引优化加速)
注意:全文检索和下面的相识搜索都需要pg_trgm插件。所以先要执行:
create extension pg_trgm;
具体SQL如下,每次输入空格用&符号代替,最后接:*表示模糊检索。to_tsvector ,to_tsquery参阅postgresql全文检索文档。
SELECT name FROM goods WHERE to_tsvector('English',name) @@ to_tsquery('English','aaa&bbb&cc:*')
通过执行计划查看速度:接近8秒
。。。。。。。
Planning time: 0.129 ms
Execution time: 7986.176 ms
通过gin索引来优化加速,这里to_tsvector('English',name)就是一个表达式索引。
CREATE INDEX name_idx ON goods USING GIN(to_tsvector('English',name));
优化后后的执行计划,速度为13毫秒左右:
explain (analyze,verbose,timing,costs,buffers) SELECT name FROM goods WHERE to_tsvector('English',name) @@ to_tsquery('English','aaa&bbb&cc:*')
=================================================
Bitmap Heap Scan on public.goods (cost=88.04..109.24 rows=5 width=33) (actual time=17.343..17.353 rows=4 loops=1)
Output: name
Recheck Cond: (to_tsvector('english'::regconfig, (goods.name)::text) @@ '''aaa'' & ''bbb'' & ''cc'':*'::tsquery)
Heap Blocks: exact=1
Buffers: shared hit=473
-> Bitmap Index Scan on name_idx (cost=0.00..88.04 rows=5 width=0) (actual time=17.334..17.334 rows=4 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (goods.name)::text) @@ '''aaa'' & ''bbb'' & ''cc'':*'::tsquery)
Buffers: shared hit=472
Planning time: 0.222 ms
Execution time: 13.381 ms
三、相似搜索
具体实现SQL,通过查询结果可以看到越相似,相似度越小,可以看到,在搜索aaa bbb的时候搜索出了aaa b6b,这就是相似搜索。
SELECT name ,name <-> 'aaa bbb' FROM goods WHERE name <-> 'aaa bbb' < 0.7 LIMIT 10
aaa bbb 0
aaa bbb ccc 0.333333
aaa ccc bbb 0.333333
aaa bbb ccc ddd 0.5
aaa b6b ccc 0.666667
aaa bbb ccsdsd 0.466667
aaa 0.5
PostgreSQL扩展知识
在第一种模糊查询中,可以使用关键字ILIKE替换LIKE, ILIKE表示字符串匹配时与大小写无关。这是一个PostgreSQL扩展、并不是标准SQL语法。
参考
【搜索引擎】 PostgreSQL 10 实时全文检索和分词、相似搜索、模糊匹配实现类似Google搜索自动提示的更多相关文章
- 【搜索引擎】Solr Suggester 实现全文检索功能-分词和和自动提示
功能需求 全文检索搜索引擎都会有这样一个功能:输入一个字符便自动提示出可选的短语: 要实现这种功能,可以利用solr的SuggestComponent,SuggestComponent这种方法利用Lu ...
- PHP+mysql数据库开发搜索功能:中英文分词+全文检索(MySQL全文检索+中文分词(SCWS))
PHP+mysql数据库开发类似百度的搜索功能:中英文分词+全文检索 中文分词: a) robbe PHP中文分词扩展: http://www.boyunjian.com/v/softd/robb ...
- Lucene全文检索_分词_复杂搜索_中文分词器
1 Lucene简介 Lucene是apache下的一个开源的全文检索引擎工具包. 1.1 全文检索(Full-text Search) 1.1.1 定义 全文检索就是先分词创建索引,再执行搜索的过 ...
- [转帖] “王者对战”之 MySQL 8 vs PostgreSQL 10
原贴地址:https://www.oschina.net/translate/showdown-mysql-8-vs-postgresql-10?lang=chs&page=2# 英文原版地址 ...
- 【ELK】【docker】【elasticsearch】1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安装ik分词器
系列文章:[建议从第二章开始] [ELK][docker][elasticsearch]1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安 ...
- “王者对战”之 MySQL 8 vs PostgreSQL 10
既然 MySQL 8 和 PostgreSQL 10 已经发布了,现在是时候回顾一下这两大开源关系型数据库是如何彼此竞争的. 在这些版本之前,人们普遍认为,Postgres 在功能集表现更出色,也因其 ...
- 重磅发布!阿里云推PostgreSQL 10 高可用版
摘要: 近日,阿里云重磅发布PostgreSQL 10 高可用本地SSD盘版,相比原 9.4 版本又新增了JSONB.BRIN索引.GROUPING SETS/CUBE/ROLLUP.UPSERT等多 ...
- PostgreSQL 10.7 linux 主从配置
PostgreSQL 10.7 主从安装 硬件环境 云服务商:华为云 Linux: CentOS7.1 工具:Xshell Xftp IP:114.115.251.168 Port: 5432 543 ...
- PostgreSQL 10 如何使用 PgAdmin3
自从 PgAdmin4 出来以后,PgAdmin3 就停止开发了,PgAdmin 官网下载的 PgAdmin3 无法支持 PostgreSQL 10 或者更高版本的数据库服务器端. 但是 PgAdmi ...
随机推荐
- WPF中样式和行为和触发器
原文:WPF中样式和行为和触发器 样式简介:样式(style)是组织和重用格式化选项的重要工具,不是使用重复的标记填充XAML,以便设置外边距.内边距.颜色以及字体等细节.而是创建一系列封装所有这些细 ...
- typescript调用javascript && URI.js
URI.js URI.js是一个用于处理URL的JavaScript库它提供了一个“jQuery风格”的API(Fluent接口,方法链接)来读写所有常规组件和许多便利方法,如.directory() ...
- JS 扩展方法prototype
通过类对象的prototype设置扩展方法,下面为String对象增加quote(两边加字符)方法 <script type="text/javascript"> St ...
- js 指向表格行变色,离开恢复
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- wpf 高DPI开发
https://blog.walterlv.com/post/windows-high-dpi-development.html https://blog.csdn.net/ZslLoveMiwa/a ...
- 【转】微信退款时候报”请求被中止: 未能创建 SSL/TLS 安全通道“或”The request was aborted: Could not create SSL/TLS secure channel“的错误
退款测试在我本机测试一切都是正常的,但是发布到了服务器就报这样的一个错啦 但是无论百度或者google或者bing,你能够搜索到的结果都很类似,综合起来就是加这样一些代码,如下 ServicePoin ...
- UWP入门(十二)--数据绑定用法
原文:UWP入门(十二)--数据绑定用法 主要几个元素: Template DataTemplate ItemSource 数据绑定是一个数据提取的方法,能使数据和UI上的控件紧密相连,下面的Demo ...
- LCID
Language Location (or type) Language ID Language tag Supported version Afar 0x1000 aa Release 9 Af ...
- nltk处理文本
nltk(Natural Language Toolkit)是处理文本的利器. 安装 pip install nltk 进入python命令行,键入nltk.download()可以下载nltk需要的 ...
- 静态dll的问题终于搞定了
导入plugin,构建qapplicationhttps://forum.qt.io/topic/60940/qt-static-dll-x64-using-qapplication-issues/2 ...