PostgreSQL 行级全文检索

在一些应用程序中,可能需要对表的所有字段进行检索,有些字段可能需要精准查询,有些字段可能需要模糊查询或全文检索。
这种需求对于应用开发人员来说,会很蛋疼,因为写SQL很麻烦,例子:

postgres=# create table t(phonenum text, info text, c1 int, c2 text, c3 text, c4 timestamp);
CREATE TABLE
postgres=# insert into t values ('13888888888','i am digoal, a postgresqler',123,'china','中华人民共和国,阿里巴巴,阿',now());
INSERT 0 1
postgres=# select * from t;
  phonenum   |            info             | c1  |  c2   |              c3              |             c4
-------------+-----------------------------+-----+-------+------------------------------+----------------------------
 13888888888 | i am digoal, a postgresqler | 123 | china | 中华人民共和国,阿里巴巴,阿 | 2016-04-19 11:15:55.208658
(1 row)

例如查询t表,条件是,任意字段匹配digoal就返回该记录。

select * from t where phonenum='digoal' or info ~ 'digoal' or c1='digoal' or ......;

每个字段都要写一个条件,有精准匹配,有全文检索。

使用行级全文检索,可以大大简化这个查询。
以结巴分词为例:
源码如下,
https://github.com/jaiminpan/pg_jieba
还有一个基于scws的pg_scws,
https://github.com/jaiminpan/pg_scws
以上都支持自定义词典。
安装略,下面看看用法:

postgres=# select t::text from t;
                                                        t
-----------------------------------------------------------------------------------------------------------------
 (13888888888,"i am digoal, a postgresqler",123,china,中华人民共和国,阿里巴巴,阿,"2016-04-19 11:15:55.208658")
(1 row)

postgres=# select to_tsvector('jiebacfg',t::text) from t;
                                                                                 to_tsvector
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 ' ':6,8,11,13,33 '04':30 '11':34 '123':17 '13888888888':2 '15':36 '19':32 '2016':28 '55.208658':38 'china':19 'digoal':9 'postgresqler':14 '中华人民共和国':21 '阿里巴巴':23
(1 row)

使用t::text可以将行转成一个大文本。

postgres=# select to_tsvector('jiebacfg',t::text) @@ to_tsquery('digoal & china') from t;
 ?column?
----------
 t
(1 row)

postgres=# select to_tsvector('jiebacfg',t::text) @@ to_tsquery('digoal & post') from t;
 ?column?
----------
 f
(1 row)

创建行级文本索引,需要用到immutable函数索引

postgres=# create or replace function f1(regconfig,text) returns tsvector as $$
 select to_tsvector($1,$2);
 $$ language sql immutable strict;
CREATE FUNCTION

postgres=# create or replace function f1(text) returns tsvector as $$
select to_tsvector($1);
$$ language sql immutable strict;
CREATE FUNCTION

postgres=# alter function record_out(record) immutable;
ALTER FUNCTION
postgres=# alter function textin(cstring) immutable;
ALTER FUNCTION
postgres=# create index idx_t_1 on t using gin (f1('jiebacfg'::regconfig,t::text)) ;
CREATE INDEX

验证:

postgres=# select * from t where f1('jiebacfg'::regconfig,t::text) @@ to_tsquery('digoal & post') ;
 phonenum | info | c1 | c2 | c3 | c4
----------+------+----+----+----+----
(0 rows)
postgres=# select * from t where f1('jiebacfg'::regconfig,t::text) @@ to_tsquery('digoal & china') ;
  phonenum   |            info             | c1  |  c2   |              c3              |             c4
-------------+-----------------------------+-----+-------+------------------------------+----------------------------
 13888888888 | i am digoal, a postgresqler | 123 | china | 中华人民共和国,阿里巴巴,阿 | 2016-04-19 11:15:55.208658
(1 row)

postgres=# select * from t where f1('jiebacfg'::regconfig,t::text) @@ to_tsquery('digoal & 阿里巴巴') ;
  phonenum   |            info             | c1  |  c2   |              c3              |             c4
-------------+-----------------------------+-----+-------+------------------------------+----------------------------
 13888888888 | i am digoal, a postgresqler | 123 | china | 中华人民共和国,阿里巴巴,阿 | 2016-04-19 11:15:55.208658
(1 row)

postgres=# explain select * from t where f1('jiebacfg'::regconfig,t::text) @@ to_tsquery('digoal & 阿里巴巴') ;
                                              QUERY PLAN
------------------------------------------------------------------------------------------------------
 Seq Scan on t  (cost=0.00..1.52 rows=1 width=140)
   Filter: (to_tsvector('jiebacfg'::regconfig, (t.*)::text) @@ to_tsquery('digoal & 阿里巴巴'::text))
(2 rows)

如果记录数很多,就会用到索引,记录数很少的时候,我们可以用hint或者开关来强制索引:

postgres=# set enable_seqscan=off;
SET
postgres=# explain select * from t where f1('jiebacfg'::regconfig,t::text) @@ to_tsquery('digoal & 阿里巴巴') ;
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on t  (cost=12.25..16.77 rows=1 width=140)
   Recheck Cond: (to_tsvector('jiebacfg'::regconfig, (t.*)::text) @@ to_tsquery('digoal & 阿里巴巴'::text))
   ->  Bitmap Index Scan on idx_t_1  (cost=0.00..12.25 rows=1 width=0)
         Index Cond: (to_tsvector('jiebacfg'::regconfig, (t.*)::text) @@ to_tsquery('digoal & 阿里巴巴'::text))
(4 rows)

happy it.

时间: 2024-08-30 02:12:38

PostgreSQL 行级全文检索的相关文章

unix:行级级触发器变通成语句级触发器-变通处理

unix培训之变通处理:我们不妨做一下变通处理.将行级级触发器变通成语句级触发器.看下面的处理. 1.创建一个package:emp_pkg . CREATE ORREPLACE PACKAGE emp_pkg AS /* ---------------------------------- --Author:Kevin.yuan --create_time: 2008 -07-01 ---------------------------------- */ TYPE crArray IS TA

浅谈Oracle的行级锁

㈠ 单实例Oracle locking机制 locking机制的三大组成部分: ① resource structure Oracle对于每个需要"并发访问"的资源,都在SGA中用一个数据结构来描述它 这个结构叫resource structure 这个数据结构有三个成员:owner.waiter和converter 这是3个指针 指向由lock structure组成的链表的指针 其中,converter和waiter有些区别: 如果某个操作先后需要两种不同模式的锁,比如,先S,后X

请教下关于oracle行级锁的问题

问题描述 我用asp.NET写了一个webservice的接口,大概代码如下log.Info("----------------------------");log.Info("获取余额中...");DataSetdsBalance=GetDataset(string.Format("selectbalancefromINTERFACE_USERwhereusercode='{0}'forupdate",userCode));if(dsBalan

PostgreSQL 会话级资源隔离探索

背景 如果一个数据库对外提供的服务,或者承载的业务很多时,你首先想到的肯定是拆分数据库. 但是,拆分毕竟是有成本的,而且有时并不是所有的场景都适合拆分来解决. 如果多个业务混合在一起使用一个数据库,就容易造成资源的争抢. 那么不拆分的情况下,控制每个业务或者每个会话的资源使用呢? 如何区分来源应用 要隔离应用使用数据库的资源,首先要区分应用. 通常如果一个数据库提供了多个业务服务时,会给每个业务创建不同的库或者分配不同的用户. 当然,如果你用了同一个库,或者同一个数据库,就分不清业务了吗?当然不

数据库事务系列-HBase行级事务模型

HBase是BigTable的开源实现,事务模型也与BigTable一脉相承 – 仅支持行级别的事务.虽然Jeff Dean大神在接受采访时公开承认目前在技术领域最后悔的事情就是没有在BigTable中加入跨行事务模型,以至于之后很多团队都在BigTable之上重复造各种各样的分布式事务轮子.这点笔者是认同的,现在确实有很多团队在HBase之上造了很多轮子(Tephra | Trafodian | Omid),试想如果这个工作做在了BigTable里面,这些团队的人是不是可以做更多其他有意义的事

MySQL行级锁、表级锁、页级锁详细介绍_Mysql

页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作.如果你是写锁,则其它进程则读也不允许行级,,仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作.页级,表级锁速度快,但冲突多,行级冲突少,但速度慢.所以取了折衷的页级,一次锁定相邻的一组记录. MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行

jQuery 行级解析读取XML文件(附源码)_jquery

最近在做一个项目,因为页面使用了Cookie,所以要判断用户的浏览器是否支持Cookie,并提示用户如何开启浏览器的Cookie功能.同时,整个项目要配置多语言支持,包括中文.越南语.日语和英语,所以必须有语言配置文件.项目中应用jQuery解析读取XML语言配置文件来实现语言的调度.这是jQuery解析读取XML文件功能的测试源码,现拿出来分享.目录结构: main.css文件代码: 复制代码 代码如下: @CHARSET "UTF-8"; * { margin: 0px; padd

Mysql 行级锁的使用及死锁的预防方案_Mysql

一.前言 mysql的InnoDB,支持事务和行级锁,可以使用行锁来处理用户提现等业务.使用mysql锁的时候有时候会出现死锁,要做好死锁的预防. 二.MySQL行级锁 行级锁又分共享锁和排他锁. 共享锁: 名词解释:共享锁又叫做读锁,所有的事务只能对其进行读操作不能写操作,加上共享锁后其他事务不能再加排他锁了只能加行级锁. 用法: SELECT `id` FROM table WHERE id in(1,2) LOCK IN SHARE MODE 结果集的数据都会加共享锁 排他锁: 名词解释:

SqlServer:行级锁问题

问题描述 刚开始研究SQL锁的问题,现在遇到了两个麻烦:一.在写SP时,设置的TimeOut无效,如果事务没有commit的话,即使超过TimeOut的时间,SP还是不能中断.是不是我哪里弄错了?是不是TimeOut不是这样子理解的?能不能给个实际的例子?网上的那些就算了,看了半天,还是不行二.我一旦锁定一行,如:UPDATEBSN_OrderWITH(ROWLOCK)SETDataSt='N'WHEREBSN_OrderSq=@OrderSq;在这行未释放之前,别的页面在访问这张资料表的时候,