博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL给模糊搜索加索引
阅读量:5916 次
发布时间:2019-06-19

本文共 3332 字,大约阅读时间需要 11 分钟。

  hot3.png

PostgrSQL有个模块叫pg_trgm,可以对字符串来进行比较相似度,并通过加GIST或者GIN索引来达到提速的效果。在一般的RDBMS中这种需求都会进行全表扫描的,但是PG如果加了这个模块,在一定场景下就可以使用索引来提速了。
一、背景
我们有一个需求根据人员的拼音码(或者药品的拼音码)进行搜索,因为拼音码不一定是全的,故通常给的方案是模糊搜索,在拼音码的首尾两端各加一个百分号,但是效率通常很慢,一般情况下也不建议这么做。
二、环境
OS:CentOS 6.5
DB:PostgreSQL 9.3
三、步骤
1.因为DB是通过源码编译的,所以创建很简单,只要添加一个扩展
his=# create extension pg_trgm;CREATE EXTENSION
2.添加索引 在添加索引前,先比较一下两者的查询消耗和速度
his=# select count(1) from tbl_user;  count  --------- 1008215(1 row)his=# explain analyze select 1 from tbl_user where user_spell like '%CYL%';                                                 QUERY PLAN                                      -------------------------------------------------------------------------------------------- Seq Scan on tbl_user  (cost=0.00..35156.69 rows=82 width=0) (actual time=0.357..693.233 rows=1021 loops=1)   Filter: ((user_spell)::text ~~ '%CYL%'::text)   Rows Removed by Filter: 1007194 Total runtime: 1193.699 ms(4 rows)
--加了索引后的查询,提高了近10倍
his=# create index idx_user_spell on tBL_user using gist (user gist_trgm_ops);CREATE INDEXhis=# explain analyze  select 1 from tbl_user where user_spell like '%CYL%';                                                          QUERY PLAN                             --------------------------------------------------------------------------------------------- Bitmap Heap Scan on tbl_user  (cost=4.92..319.11 rows=82 width=0) (actual time=117.652..120.849 rows=1021 loops=1)   Recheck Cond: ((user_spell)::text ~~ '%CYL%'::text)   Rows Removed by Index Recheck: 2   ->  Bitmap Index Scan on idx_user_spell  (cost=0.00..4.90 rows=82 width=0) (actual time=117.291..117.291 rows=1023 loops=1)         Index Cond: ((user_spell)::text ~~ '%CYL%'::text) Total runtime: 121.098 ms(6 rows)
四、说明
可以看出来模糊搜索也走了索引,速度有了很大提升,COST也减小很多。这个模块在官网上可以看到有几个自带的函数,主要示例如下:
1.similarity(text,text)
这个函数是用来比较两个字符串的相近程度的,取值范围在0-1之间,完全相同为1,完全不同则为0
his=# select similarity('123','789'); similarity ------------          0(1 row)his=# select similarity('123','123'); similarity ------------          1(1 row)his=# select similarity('123','12345'); similarity ------------        0.428571(1 row)--和相似度相反的是他的操作符<->,这个操作符表示的是两组字符串的一个距离,如果是一样的,则是重合的,距离为0,如果完全不同,则为1,算法实际就是1减去上面这个相似值,比如以下例子:his=# select '123'<->'123','123'<->'12345','123'<->'678'; ?column? | ?column? | ?column? ----------+----------+----------        0 | 0.571429 |        1(1 row)
2.show_trgm(text) 这个函数返回的一串字符数组,有点类似于全文检索的分词,可以用这个函数来做一些Debug
his=# select show_trgm('123'),show_trgm('1234');        show_trgm        |          show_trgm          -------------------------+----------------------------- {"  1"," 12",123,"23 "} | {"  1"," 12",123,234,"34 "}(1 row)--上面的相似度就是用的这个分词分出来的,比如123和1234,相同的值有3个,总的不同值有6个,所以相似度是3/6=0.5--这个函数可以看出对字符数字能有些进行切割,但是对汉字暂时还无能为力,有一定的限制his=# select show_trgm('中国人民'),show_trgm('中国人民12'); show_trgm |      show_trgm      -----------+--------------------- {}        | {"  1"," 12","12 "}(1 row)his=# select similarity('中国人','日本'),similarity('中国人','中国人'); similarity | similarity ------------+------------          0 |          0(1 row)
五、优点与不足
1.使用这个模块可以对需要使用模糊检索字符串的数据进行加索引提速
2.对字母或数字的相似度比较较为满意,对汉字还不支持
3.如果模糊检索的数据结果集较大,运行速度可能比较慢,比如只搜索一个字母匹配的 %C%
六、参考
1.http://www.postgresql.org/docs/9.4/static/pgtrgm.html 2.http://blog.163.com/digoal@126/blog/static/163877040201191882553803/

转载于:https://my.oschina.net/Kenyon/blog/366505

你可能感兴趣的文章
ZABBIX监控mysql主从状态
查看>>
jmeter连接数据库
查看>>
博客作业05--查找
查看>>
[Windows]Visual Studio Code个人配置
查看>>
方法论:怎样练习一万小时
查看>>
java框架问题整理
查看>>
Xcode
查看>>
原生js实现触摸滚动轮播图
查看>>
DbContext 和ObjectContext两者的区别
查看>>
Codeforces 847C - Sum of Nestings
查看>>
网络编程
查看>>
加密解密以及CA签证
查看>>
[Android]apk反编译方法
查看>>
如何获取SQL Server数据库连接字符串的某些部分
查看>>
static的作用
查看>>
10个必需的iOS开发工具和资源
查看>>
后台修改js或者css文件之后,客户端刷新但是无效的问题
查看>>
mongodb 表达式
查看>>
hibernate 5.x版本中中schemaexport的使用
查看>>
div下的img标签中图片的大小设定
查看>>