4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,企业版 4核16GB
推荐场景:
HTAP混合负载
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)

开发者学堂课程【PostgreSQL快速入门:4 PostgreSQL 索引,全文检索模糊匹配,近似度匹配(三)】学习笔记与课程紧密联系,让用户快速学习知识

课程地址https://developer.aliyun.com/learning/course/16/detail/90


4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)

 

内容介绍

十一、HOT Update

十二、PostgreSQL 全文检索

十三、pg_trgm 近似匹配

十四练习

十一、HOT Update

1、索引指针结构

2、ItemPointers (index) ->索引中存储指向数据linepointlinepoint在heap page中,ItemPointers在索引页中linepoint是ctidlinepoint10号数据块的第一条记录linepoint20号数据库第二条记录hot当记录在发生变更tuple1还在,ItemPointers不需要变更不需要指向linepoint2,linepoint1指向tuple2,tuple2指向linepoint2,linepoint2执行tuple2。

image.png

回收掉之后linepoint1直接指向linepoint2,linepoint2指向tuple2。

image.png

利用pageinspect extension 来观察HOT

postgres= # create extension pageinspect;创建

Get_raw_page是指把hot_test0号数据块的罗数据去取出来

Page_header是取出头部信息包含isnlowerupper等

postgres= # create table hot_ test (id int primary key,info text);创建测试表

postgres =# insert into hot_ test values (1,'digoal');

因为是从0page开始插入, 这里就省去了查询ctid等过程 直接切入0page

当前的page信息

postgres =# select * from page_ header(get_raw_ page('hot_ _test',0)));

lsn I tli I flags I lower l upper I special I pagesize I version prune_ xid

2/75B27878I 1 I 0 I 28I 8152I 8192I 8192I 4 I 0

当前的item信息

postgres =# select * from heap_ page_ items(get raw_ _page('hot test',0));只有一条记录当前执行的ctid是0,1,进行更新

当前索引的page信息

postgres # select * from page. _header(get. raw_ _page('hot_ test_ pkey',0);

lsn Itli Iflags l lower I upper I special I pagesize I version I prune _xid

2/75B278B|1|0|48|8176|8176|8192|4|0

当前索引的item信息

postgres= # select * from heap. _page items(get_ raw_ _page('hot test_ pkey',0);索引当前只有一个指向0,1

进行update hot test set info new where id ghri第一条记录被更新t_xmax变成更新的事物id,1881条记录变成新纪录新行版本tid变成0,2,就是hot起的作用跟图里是一样的指向第二条记录

第一条记录指向第二条记录vacuum有变化回收第一条记录不指向第二条记录变成空记录变成第二幅图所示linepoint1还是存在只是指向了linepoint2,linepoint2直接指向tuple2。

如果发生多次操作update很多次会生成很多个版本

postgres= # update hot_ test set info= 'new' where id=1;

postgres=# update hot_ test set info='new' where id=1;

postgres= # update hot_ test set info='new' where id= 1;

postgres= # update hot_ test set info= 'new' where id= 1;

postgres=# update hot_ test set info='new' where id=1; ,

postgres=# update hot_ test set info='new' where id=1;

会发现串行指向记录没有被回收掉只是指向了下一条被更新的记录vacuum之后都会回收跟第二幅图一样

image.png

第一条记录一直都在指向真实数据

 

十二、PostgreSQL 全文检索

和全文检索相关的有两个数据类型

tsvector 文本在经过全文检索标准化处理后得到类型,处理后的文本包括(分词去重复后排序,分词的位置,分词的权重结构(共可以指

定4个权重ABCD, D默认不显示))

tsquery 需要检索的分词组合,组合类型包括&,|,!(与,或,否)同时还支持分词的权重,分词的前导匹配

详细介绍

htp://www postgrcsql.org/docs/9.3/static/datatypc-textscarch.html

htp://www. postgresql or/docs/9.3/static/textsearch html

字符串到tsvector的默认转换例子:

digoal=# select SShello world, i'm digals.s:tsvector;

tsvector

'digoal.' "hello' "m' 'world,'

这种转换后得到的tsvector不包含分词的位置信息和权重信息.只有排序后的分词

权重和位置信息可以提现在文本中(权重一般用来表示该分词所在的级别,如目录,或正文? ),

digoal=# select $$hello:1b world:1a i'm:3D digas.s::tsvector,

tsvector加了权重的分词hello放在第一的位置,权重是bd是默认的所以不会显示

'digoal.' "hello':1B 'i"m':3 'world,:1A大写

使用to_tsvector, 可以指定不同的语言配置,把文本根据指定的语言配置进行分词。

例如,使用西班牙语和英语得到的tsvector值是不一样的。

digoal=# select to_ tsvector'english', SSHello world, I'm digoal.SS);

to_ tsvector

'digoal':5 "hello':1 'm':4 'world':2

(1 row)

digoal=# select to. tsvector('spanish',  $$Hello world, I'm digoal.SS);

to_ tsvector

'digoal':5 hell':1 ':3 'm':4 'world':2

(1 row)

查看系统中已经安装的全文检索配置。

digoal=#\ dF *

List of test search configurations

Schemal NameI

Description

pg_ catalog I danishI configuration for danish language

pg_ catalog I Idutch I configuration for dutch language

pg_ catalog I english I configuration for english language

pg_ catalog I finnishI configuration for finnish language

pg_ catalog I french I configuration for french language

Pg_ catalog I german I configuration for german language

pg_ catalog I hungarian I configuration for hungarian language

pg_ catalog I italianI configuration for italian language

pg_ catalog I norwegianI configuration for norwegian language

pg. catalog I portuguese I configuration for portuguese language

pg_ catalog I romanian I configuration for romanian language

pg_ catalog I russian I configuration for russian language

pg_ catalog I simple I simple configuration

pg_ catalog I spanish I configuration for spanish language

pg_ catalog I swedishI configuration for swedish language

pg_ catalog I turkish I configuration for turkish language

后面的例子中会有中文的安装

tsquery的例子

&,|,!组合,分组使用括号

SELECT 'fat & rt::tsquery;

tsquery

'far'&rat’

SELECT 'fat & (rat cat)::tsquery;

tsquery

'fat' & ( 'rat'|'cat' )

SELECT 'fat & rat & ! cat::tsquery;

tsquery

'fat' & 'rat' & !'cat*

支持指定权重

SELECT 'fat:ab & cat'::tsquery;

tsquery

'fat':AB & 'cat*

支持前导匹配

SELECT 'super:*::tsquery;

tsquery

'super':*

使用to_ tsquery转换时,也可以带上语言配置

digoal=# SELECT to_ tsquery('english', 'Fat:ab & Cats');

to_ tsquery

'fat':AB & 'cat'

和全文检索相关的函数和操作符

Operator

Description

Example

Result

@@

tsvector matches tsquery ?查询的分词是否在分词列里面

to_ tsvector(' fat cats ate rats' ) @@ to_ tsquery(' cat a rat' )

t

@@@

deprecated synonym for @@

to_ tsvector(' fat cats ate rats' ) @@@ to_ tsquery(' cat a rat' )

t

||合并

concatenate tsvectorS

b:2' ::tsvectorll' c:1 d:2 b:3' ::tsvector

a' :1 'b' :2,5 'c':3 'd' ;4

&&

AND tsqueryS together

fatI rat' ::tsquery &&' cat.',: : tsquery

( ' fat' I ' rat') &'cat'

||把值进行合并

OR tsqueryS together

fatI rat' :: tsquery||' cat' : : tsquery

('fat'I'rat')I'cat'

!!

negate a tsquery

!!

cat'

:: tsquery进行反转

!' cat'

@>包含

tsquery contains another ?

cat' : : tsquery

@>cat@Rat::

tsquery

f

<@

tsquery is contained in ?

cat' : : tsquery

<@cat@Rat::

tsquery

t

全文检索的索引使用

digoal= =# create table ts(id int, info tsvector, crt_ time timestamp);

CREATE TABLE

digoal=# insert into ts values (1, $$Hello world, i'm digoal.$$, now());

INSERT0 1

digoal=# create index idx_ ts_ 1 on ts using gin (info);

CREATE INDEX

digoal=# select * from ts where info @@ 'digol.::tsquery;使用gin索引支持@@,是否包含tsquery

id  info crt_ time

1 I 'Hello' 'digoal.' 'i"m' 'world,' I 2013-12-09 16:35:55.635111

(1 row)

全文检索的索引使用(svector支持的素索引策略gin, gist, btree)

GIN索引策略,可用itsvector包含tsquery的查询匹配。

digoal= # set enable_ seqscan=off;全链扫描关闭

SET

digoal= # explain analyze select * from ts where info @@ 'digoal'::tsquery;

QUERY PLAN

Bitmap Heap Scan on ts (cost=2.00..3.01 rows=1 width=44) (actual time=0.02 1 ..0.021 rows=1 loops=1)

Recheck Cond: (info @@ "didgol.":squery)

> Bitmap Index Scan on idx_ ts_ 1 (cost=0.00..2.00 rows=1width=()) (actual time=0.016..0.016 rows=1 loops=1)

Index Cond: (info @@ "digol":tsquery)

Total runtime: 0.061 ms

(5 rows)数据库全文检索支持索引

全文检索的索引使用

GiST索引策略,可用于包含匹配

digoal=# drop index idx_ ts_ 1;

DROP INDEX

digoal=# create index idx _ts_ 1 on ts using gist (info);

CREATE INDEX

digoal=# explain analyze select * from ts where info @@ 'digoal.::tsquery;

QUERY PLAN

Index Scan usingidx_ ts_ 1 on ts (cost=0. 12..2.14 rows=l width=44) (actual time=0.016..0.017 rows=l loops=l)

Index Cond: (info @@ "igoal."::tsquery)

Total runtime: 0.055 ms

(3 rows)

中文全文检索举例,中文检索有很多种对于postgresql本身没有中文分词库需要外部的插件支持腾讯有中文解析插件

http://blog. 163.com/digoal@126/blog/static/163877040201252141010693/

中文全文检索语言配置安装简介

下载进行部署

Cent0S 5. x 64bit

PostgreSQL 9. 1.3

nlpbanboo-1.1. 2

cmake-2.8.8

CRF++-0.57

安装cmake

tar -zxvf cmake -2.8.8.tar.gz

cd cmake-2.8.8

./bootstrap --prefix =/opt/cmake2.8.8

gmake

gmake install

vi ~/.bash_ profile

export PATH=/opt/cmake2.8.8/bin:$PATH

. ~/.bash_ profile

如果不用数据库全文检索在数据库中支持全文检索类型在分词之后进行匹配效率还行对于大型的搜索引擎网站不会用到它们会用专用的搜索引擎对于小网站不想另外部署搜索引擎可以使用这种方法

安装crf

tar -zxvfCRF++-0.57.tar.gz

cd CRF++-0.57

Jconfigure

gmake

gmake install

提示把目录/usr/local/lib加到piggrep下面打印可以看到文件已经存在

安装nlpbamboo

vi ~/.bash_ profile

export PGHOME=/opt/pgsql依赖pgsql

export PATH=$PGHOME/bin:/opt/bamboo/bin:/opt/emake2.8.8/bin:$PATH:.

export LD_ LIBRARY_ PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:.

, ~/.bash_profile

tar -jxvf nlpbamboo-l.l 2.tar.bz2

cd nlpbamboo-1.1.2

mkdir build

cd build

cmake .. -DCMAKE_ BUILD_ TYPE=release

gmake all

gmake install

加入lib库链接

echo "/usr/lib" >>/etc/ld. so. conf 这个命令是bamboo对应的动态链接库)

echo "/usr/local/lib" >>/etc/1d. so. conf 6这个命令是CF对应的动态链接库)

ldconfig -f /etc/ld so. conf

测试是否加入正常

1dconfig -plerep bambo

libbamboo. so.2 aibe6, x86-64) =h)

usr/1ib/libbamboo. so.2

libbunboo. so Qibe6, x86-64) => /usr/1ib/libbanboo. s0

1dconfig -plorep erf

liberfpp. so.0 01ibc6, x86-64) => /usr/1oce1/1ib/liberfpp. so. 0

liberfpp so Qibc6, x86-64) => /usr/1oce1/1ib/1iberfpp. so

加入索引

ed /opt/bamboc

wget http: //nlpbanboo. googlecode. com/ files/index. tar. br2

tar -jxvf index, tar. bz2

编译PostgreSQL支持模块

cd /opt/banboo/ exts/postares/ chinese_parser

make

make install

touch $PGHOME/ share/tsearch_data/ chinese _utf8. stop

ed 1 opt/banboo/ exts/ postgres/pe_tokenize

make

make install

安装PostgreSQL支持模块

su - poslares

ed $PGHOUE/ share/ contrib/

psql -h 127.0.0.1 postgres postgres -f chinese. parser. sql

psql -h 127.0.0.1 postgres postgres -f Pe_tokenize. sql

查看全文检索配置中加入了chinesecfg的配置

Postares=# select * from pg ts config

中文分词安装好了

测试tokenize分词函数

postgres=# select * from tokenize( ‘你好我是中国人' );

拆成五个分词

postgres=# select * from tokenize(中华人民共和国):

不会被拆是完整的词百度也是完整词今年是龙年被拆成三个

测试全文检索类型转换函数

posteres-# select *from to tsvector<’ chineseefg' ,你好我中国人目前在杭州斯凯做数据库相关的工作);

指定中文的分词

' 中国':5’你好':1 '在:9'我':3 数据库':13斯凯':‘是’:4杭州:10 '的':15 '目前':8 '相关:14负责’:12

中文分词可以使用

table blog <id serial prinary key, user id int8, title text, content text, ts title tsvector,ts_content tsvector>;

在tsvector的字段上可以使用gist索引,或者gin索引,加速检索。

postgres=# create index idk_ blog ,ts1 on blog using gist(ts. title);

CREATE INDEX

postgres=# create index idk_ blog_ ts2 on blog using gist (ts_ content):

CREATE INDEX

插入测试内容:

posteres=# insert into bloε (user_ id, title, content, ts_ title, ts. content) values (1,' PostoreSQL 叫Q群FAQ贴- 1',' Q群里些网友问到的问题,收集如下:

目录:

PostereSQL存储过程中自定义异常怎么弄?

Poster eSQIL9. 1的同步事务在某些情况下用户主动canecel等待syne replication standby的acknowledge,实际本地已提交。

PostereSQL加何满足已经存在则更新,不存在则插入的需求。

copy和insert哪个效率高?

PostgreSQL能不能限制数据库的大小?

怎样给一个用户授予只读角色?

不想让数据插入到某个表应该怎么做?

PostgreSQL中有没有r ownun这样的,显示结果集的序号?

PostgreSQL函数中如何使用savepoint?

请问,pe脚本有宏替换,计算字符串公式的能力?类似s=2 ; evsaluate(5-a) :如果将这个值赋值给这个变里呢? zresult =

evaluate(5-a)

UPDATE A表FROM B表?

hex转decinal

标题

PostereSQL时区.' , to. _tswector ( chinesecfd,' PostereSQL ∞群FAQ贴- 1' ), to, _tswector ( chinesecfd ,' Q群里些网友问到的问题,收集如下:

目录

内容

Poster eSQL存储过程中自定义异常怎么弄?

PostereSQL9. 1的同步事务在某些情况下用户主动cance1等待syne replicati on st andby的aclnowledge,实际本地已提交。

Poster eSQL如何满足已经存在则更新,不存在则插入的需求。

copy和insert哪个效率高?

PostereSQL能不能限制数据库的大小? 上怎样给一个用户授予只读角色?

不想让数据插入到某个表应该怎么做?

PostgreSQL 中有没有r ornun这样的,显示结果集的序号?

PostereSQL 函数中如何使用savepoint?

请问,pd脚本有宏替换,计算字符串公式的能力?类似o=2 ; evaluate(5-a) ;如果将这个值赋值给这个变童呢? zresult =

evaluate(5-a) ;

UPDATE A表FROM B表?

hex转decimal

PostereSQL时区' ));

标题拆分词组内容拆分词组

从上面的全文检索类型字段ts_content可以看出,函数和表在这分词里面使用函数和表作为匹配条件查询时将返回结果,换个不存在的查询则没有结果:

postgres=# select user. id, title from blog where ts_content @@to_ tsquery(函数&中国’);

没有

postgres=# select user. id, title from blog where ts_content @@to_ tsquery(函数&’);

用scan索引进行匹配

 

十三、pg_trgm 近似匹配

跟中文检索不一样

pg _trgm插件

使用:http://blog. 163.com/digoal@ 126/blog/static/1638770402013416102141801/

image.png

说明:http://www. postgresql org/docs/9.3/static/pgtrgm html

原理

创建数据库时已经把所有的contrib插件编译好直接extesion pg_trgn即可在编译数据库时没有使用pgtrgm,先在源码中进行编译生成函数,similarity (text,text)字符相似度是多少

select similarity<' abc‘adb>;

0.142857

select similarity<' abc‘abd>;

0.333333

根据show_ tran (text)算出

abc

<‘’a‘’‘’ab‘’‘’abc‘’‘’bc‘’>

abd

<‘’a‘’‘’ab‘’‘’abd‘’‘’bd‘’>

第一个相似第二个相似第三个不相似第四个不相似

加起来总共有六个单元相似的有两个,2处以6得到0.333333,这就是相似度拆分成完全不一样的

<"a"," ab",abc , "bc ",‘’bca‘’, cab>

<"a"," ab",abc , "abd ",‘’bca‘’, cab>

一共有8个元素相似的有五个近似度0.625。

相似度大于50%返回可以走索引创建表创建索引使用索引时使用操作符也可以用gin操作符

CREATE TABLE test_ trgn(t text):

CREATE NDEX trgm_ idx ON test_ tra USING ist( t gist_ tram ops):

show_ limit (),set. limit(real)相似的力度超过百分之30的相似度字符被认为很相似t%word’返回真

abc%abd认为是相似的返回t真abcadb是f只有百分之14的相似度通过索引检测相似度情况可以用于日志的相似度返回f也可以用于输错了字的顺序也可以进行匹配比全文扫描分词的方法更加彻底完全把字符串按照连续个数字符串分段拆成3个一组的单元做两者近似度的匹配更加适合于人名其中有一个错了如果近似度够也可以匹配出来

 

十四、练习

1、各种索引的合理使用。

2、全文检索的使用以及中文分词插件的安装和使用。

3、近似匹配插件pg_trgm的安装和使用

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
11天前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用问题之mysql迁移后查询不走索引了,该如何解决
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
11天前
|
运维 关系型数据库 分布式数据库
PolarDB产品使用问题之列存索引的原理是什么
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
26天前
|
存储 算法 数据处理
惊人!PolarDB-X 存储引擎核心技术的索引回表优化如此神奇!
【6月更文挑战第11天】PolarDB-X存储引擎以其索引回表优化技术引领数据库发展,提升数据检索速度,优化磁盘I/O,确保系统在高并发场景下的稳定与快速响应。通过示例代码展示了在查询操作中如何利用该技术高效获取结果。索引回表优化具备出色性能、高度可扩展性和适应性,为应对大数据量和复杂业务提供保障,助力企业与开发者实现更高效的数据处理。
|
10天前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之如何查看SQL语句使用的是行索引还是列索引
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
2月前
|
关系型数据库 数据库 索引
|
2月前
|
监控 关系型数据库 数据库
关系型数据库考虑索引的选择性
【5月更文挑战第20天】
36 4
|
2月前
|
SQL Oracle 关系型数据库
关系型数据库中对索引的数目
【5月更文挑战第19天】
53 4
|
2月前
|
监控 关系型数据库 数据库
|
1月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用合集之表列存索引要怎么添加
PolarDB是阿里云推出的一种云原生数据库服务,专为云设计,提供兼容MySQL、PostgreSQL的高性能、低成本、弹性可扩展的数据库解决方案,可以有效地管理和优化PolarDB实例,确保数据库服务的稳定、高效运行。以下是使用PolarDB产品的一些建议和最佳实践合集。
|
1月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用合集之优化器对索引的阈值一般是多少
PolarDB是阿里云推出的一种云原生数据库服务,专为云设计,提供兼容MySQL、PostgreSQL的高性能、低成本、弹性可扩展的数据库解决方案,可以有效地管理和优化PolarDB实例,确保数据库服务的稳定、高效运行。以下是使用PolarDB产品的一些建议和最佳实践合集。