【搜索引擎】 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 ...
随机推荐
- MVC 行为过滤器
using FilterExam.Fiter;using System;using System.Collections.Generic;using System.Linq;using System. ...
- C#/WPF 计算字串的真实长度,调整控件的宽度
下面函数是经常用到的计算字串长度的方法: private double MeasureTextWidth(String str, string fontName, double fon ...
- Flutter 开发环境搭建
Flutter 开发环境搭建 官方的资料相对还是比较全面的,包含了很多中文的资料信息.官方对咱们国家的开发人员还是很友好的. 安装教程:https://flutter.io/get-started/i ...
- Android零基础入门第50节:StackView卡片堆叠
原文:Android零基础入门第50节:StackView卡片堆叠 上一期学习了AdapterViewFilpper的使用,你已经掌握了吗?本期开始学习StackView的使用. 一.认识StackV ...
- INS-13001—win10系统安装oracle11g时遇到INS-13001环境不满足最低要求
升级win10系统之后,需要重新安装Oracle,因为在安装Oralce11g时,使用64位的会出现各种不兼容问题,我每次安装都是使用32位的数据库. 在安装时点击setup.exe之后,出现了:[I ...
- 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(1)
前言对于WPF和Silverlight来讲,MVVM是微软设计师和业内专家高度推荐的非常棒的一种设计模式.本书会探讨MVVM设计模式的一些自身缺陷以及为什么MVVM还不能成为行业内的标准设计模式.这会 ...
- wchar_t string on Linux, OS X and Windows
Making wchar_t work on Linux, OS X and Windows for CMarkup release 10.1 I learned a couple of humble ...
- 逆向工程mybatis-geneator.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration ...
- 关于 win32 下磁盘的遍历方法
最近要写个在线专杀的东东,虽然是专杀(本来只要清除几个特定的文件和杀几个特定的进程,然后把用户的注册表恢复正常,很多病毒木马最喜欢干的一件事情就是写 映像劫持 然后机器一重启,安全相关的软件全部玩完了 ...
- QtStaticBuildScript(会有这么容易)
https://github.com/dankrusi/QtStaticBuildScript