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 索引,全文检索,模糊匹配,近似度匹配(二)

 

内容介绍

、索引合并查询

、索引和collate的匹配

、部分值索引

、函数索引和表达式索引

函数和表达式索引

六、索引合并查询

1、Combining Multiple Indexes

src/backend/executor

例如

image.png

比如有两个查询条件是andor的查询条件并且两个列都创建了索引就可以走bitmap的合并相当于使用索引取出的数据tupleaaddr进行bitmap最后给上面的节点扫描bitmapand或者bitmapor的结果集

2、Combining Multiple Indexes

单列索引的多条件匹配合并

postgres= # create table test (id int primary key,info text unique);

postgres= # insert into test select

generate_ series(1,10000o),' 'digoal'llgenerate_

_series(1,10оо00);

postgres= # explain analyze select * from test where id=1 or id= 1000;

Bitmap Heap Scan on test (cost=8.54..16.20 rows=2 width=36) (actual

time=0.034..0.036 rows= =2 loops=1)

Recheck Cond: ((id= 1) OR (id = 1000))

>BitmapOr (cost=8.54..8.54 rows=2 width=o) (actual time=0.023..0.023

rows=o loops=1)

> Bitmap Index Scan on test_ pkey (cost= O.00..4.27 rows=1 width=o)

(actual time=0.012..O.012 rows=1 loops=1)

Index Cond: (id= 1)

>

Bitmap Index Scan on test_ pkey (cost=0.00..4.27 rows=1 width=o)分成两个节点走索引扫描同时再对扫描出来的结果cpid做排序去上面的节点BitmapOr,Bitmap Heap Scan节点做最后的数据

(actual time=0.oo9..o.0o9 rows=1 loops=1)

Index Cond: (id = 1000)

 

七、索引和collate的匹配

collection

例子

CREATE TABLE test1c (

id integer,

content varchar COLLATE "x"创建表,collection是x

);

CREATE INDEX test1c_ content_ index ON test1c (content);强制指定

SELECT * FROM test1c WHERE content > constant;可能不走索引

以下SQL不能使用索引test1c_ content_ index

SELECT * FROM test1c WHERE content > constant COLLATE "y";

需建立与y COLLATE对应的索引,以上这条SQL才会走索引。

CREATE INDEX test1c_ content_ y_ index ON test1c (content COLLATE "y");在查询时

如果创建的索引的collection和字段上面存储的collection,查询所要的collection不一样不会走索引创建的索引不是collection,在查询时指定y也不会走索引创建的collection y跟创建的colatr x也是不会走索引创建索引时指定collection y即可

 

八、部分值索引

1、partial index

postgres里面允许对某些值创建索引表里面字段里面只关心

例子where id不等于1的值只对不等1的创建索引好处是索引很小检索的值可能是一小部分创建的是很小的数据

部分约束

去除common值id=1,这个值有10W条,走索引根本不合适,partial 索引很好的避免了此类情况。

postgres= # create table test(id int,info text);

postgres= # insert into test select 1,' digoal'||generate_ series(1,100000);

postgres= # insert into test select

generate_ series(1,1000),digoal'||generate_series(1,100o);

postgres= # create index idx_ test_ 1 on test(id) where id<>1;

postgres= # explain select * from test where id=1;

5"7

Seq Scan on test (cost=0.00..1791.00 rows=100000 width=15)

Filter: (id= 1)

postgres= # explain select * from test where id=10O;

Index Scan using idx_ test_ 1 on test (cost=o.oo..8.27 rows=1 width=15)

Index Cond: (id = 100)

2、部分索引在非索引列的使用

postgres= # explain select * from test where info='digoal' and id=1;

QUERY PLAN

Seq Scan on test (cost=0.00..2041.00 rows=1 width=15)

Filter: ((info = 'digoal'::text) AND (id = 1))

postgres= # create index idx_ test_2 on test(id) where info='digoalioo';索引列创建在虚拟列上面检索时也可以走索引

postgres= # explain select * from test where info='digoalioo';在某一个查询中带一个条件再创建索引

QUERY PLAN

Index Scan using idx_ test_ 2 on test (cost=0.00..8.27 rows=1 width=15)

(1 row)

3、部分索引的好处,为什么要去除common值

postgres= # drop index idx_test_ 1;

postgres= # drop index idx_test _2;

postgres= # explain select * from test where id=1;

QUERY PLAN

Seq Scan on test (cost=0.00..1791.00 rows= 100000 width=15)

Filter: (id = 1)创建的索引没有用可以把id=1排除

为什么会走全表扫描

postgres= # select id,count(*) from test group by id order by count(*) desc limit 10;

id I count

1100001 对频繁出现的值id等于1的值出现了100001

1201其它值出现很少id走索引不合理可以把id排除掉

8871

6811

id不等于1,创建的索引只会出现清晰的

 

九、函数索引和表达式索引

1、表达式索引

postgres= # explain select * from test where id+1=100;

QUERY PLAN

Seq Scan on test (cost=0.00..2059.86 rows=505 width=15)

Filter: ((id + 1)= 100)

postgres= # create index idx_ test_ 1 on test((id+1));

CREATE INDEX

postgres= # explain select * from test where id+1= 100;

QUERY PLAN

Bitmap Heap Scan on test (cost= 12.18..577.45 rows=505 width=15)

Recheck Cond: ((id + 1)= 100)

> Bitmap Index Scan on idx_ test_ 1 (cost=0.00..12.05 rows=505 width=0)

Index Cond: ((id + 1)= 100)

函数创建索引必须是seq在进行where条件查询时where里面的函数传入相同的值只会计算一遍如果传入同样的参数得到的值跟调用值不一样不允许走索引扫描如果传入同样的参数得到的值不一样创建索引没有任何意义做函数匹配时发现变量的值跟创建索引时的函数所产生的值不一样如果创建函数索引函数输入同样的参数得到的值不管调用多少次都一样返回的结果也是一样的只有这种函数才能拿来做函数索引表达式索引也是类似的,+对应函数也是seq函数

2、函数索引

以下区分大小写的场景无法使查询走普通的索引。

postgres= # create table test (id int,info text,crt_time timestamp(o));

postgres= # insert into test select

generate_ series(1,100000),' digoal'||generate_ series(1,100000),clock_ timestamp(

);

postgres= # create index idx_ test_ info on test(info);

postgres= # explain select * from test where info~*'^a';

Seq Scan on test (cost= 0.00..1887.00 rows=10 width=23)

Filter: (info ~*'^:':text)

忽略大小写的ilike和~*要走索引的话,开头的字符只能是大小写一致的,字母不行,数字可以,例如字母a区分大小写,数字0不区分大小写索引中的条目也就有别。

postgres= # explain select * from test where info{~* '^0';

Index Scan using idx_ .test_ info on test (cost=0.00..8.28 rows=10 width=23)

Index Cond: ((info >= 'o':text) AND (info < '1'::text))

Filter: (info ~* '^o'::text)

 

十、函数和表达式索引

1、函数索引

要让字母也可以走忽略大小写的索引如何做呢?

函数索引,但是函数必顷是immutable状态的,才能创建函数索引其他状态不能创建函数索引

过滤条件中也必须使用和创建的索引相同声明。

postgres= # select proname,provolatile from pg_proc where proname= 'lower';

proname| provolatile

Lower|i

postgres= # create index idx_ test_info_ 1 on test(lower(info));

CREATE INDEX

postgres= # explain select * from testwhere lower(info) ~ '^a';区分大小写可以用函数先转换成lower的字母再匹配

Bitmap Heap Scan on test (cost= 13.40..648.99 rows=500 width=23)

Filter: (lower(info) ~ '^ a'::text)

> Bitmap Index Scan on idx_ test_ jinfo_ 1 (cost=0.00..13.27 rows=500 width=0)

Index Cond: (lower(info) >= a:text) AND (lower(info) < 'b'::text))

(4 rows)

2、作为查询条件的函数或常量或变量或子查询

优化器需要知道给operator的参数值才能通过pg_statistic中 统计到的表柱状图来计算走索引还是走全表扫描戈者其他planner的开销最小,如果传入的是个变量则通常不能使用索引扫描。

几个时间函数的稳定性:

postgres= # create index idx_test_ 1 on test (crt_time);

postgres= # select proname,proargtypes,provolatile from Pg_proc where通过proc字段查询

prorettype in (1114,1184) order by proargtypes;

proname| proargtypes | provolatile

transaction_ timestamp||s

statement_ timestamp||s

pg_ stat_ get_ bgwriter_stat_ .reset_time||s

pg. . conf_ load_time||s

pg_ postmaster_ start_ time||s

pg _last_xact_replay_ timestamp||v

3、作为查询条件的函数或常量或变量或子查询

clock_ timestamp||v

Now||s

postgres= # explain select * from test where crt_ time = clock_timestamp();作为查询条件的函数至少不会是stampcrt_ time上面有索引,输入的查询条件是函数

不知道每次调用的结果所以每条记录都会调用函数根据函数得到的结果集进行匹配

Seq Scan on test (cost=0.0...2137.00 rows=100000 width=23)

Filter: (crt_time = clock_timestamp())输入的查询条件

postgres= # explain select * from test where crt_ time = now();

Index Scan using idx_ test_ 1 on test (cost=0.00..8.28 rows=1 width=23)

Index Cond: (crt_ time = now())

postgres= # alter function now() strict volatile;

postgres= # explain select * from test where crt_ time = now();不走索引也会变成连续扫描

Seq Scan on test (cost=0.00..2137.00 rowS=100000 width=23)

Filter: (crt_time = now())

作为查询条件的函数或常量或变量或子查询

postgres= # alter function clock_timestamp() strict immutable;

ALTER FUNCTION

postgres= # explain select * from test where crt_time = clock_timestamp();

QUERY PLAN

Index Scan using idx_test_ 1 on test (cost=0.00..8.28 rows=1 width=23)

Index Cond: (crt_time = '2012-04-30 15:32:02.559888+ o8' :timestamp with time zone)

作为过滤条件的函数, immutable和stable的函数在优化器开始计算COST前会把函数值算出来,而volatile的函数,是在执行SQL的时候运行的,所以无法在优化器计算执行计划的阶段得到函数值,也就无法和pg_ statistic中的信息比对到底是走索引呢还是全表扫描或其

他执行计划。

4、表达式作为过滤条件时,同样的道理,表达式不会在优化器计算执行计划的过程中运算,所以也不能走最优的执行计划。

postgres= # explain select * from test where crt_ time = (select now());

QUERY PLAN

Seq Scan on test (cost=0.01..1887.01 rows=100000 width=23)

Filter: (crt_ timne = $0)

InitPlan 1 (returns $0)

> Result (cost=0.0..0.01 rows=1 width=0)

(4 rows)

绑定变量的使用场景,通常需要5次后得到generic plan。执行计划前五次都要进行评估下次再进行同样的sql语句使用的是generic plan,不是class plan通过generic plan的到的成本和generic plan当时存储的成本相差很大的情况才会重新计算出class plan

htp:/blog.163.com/digoal@126/blgstatic/1638770402012112452432251/

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
存储 SQL 缓存
mysql覆盖索引详解——like模糊全匹配中使用索引
mysql覆盖索引详解——like模糊全匹配中使用索引
1056 0
mysql覆盖索引详解——like模糊全匹配中使用索引
|
SQL 存储 前端开发
MySQL模糊查询 先展示精确查询在展示模糊查询结果 | 结果按匹配度 排序
MySQL模糊查询 先展示精确查询在展示模糊查询结果 | 结果按匹配度 排序
567 0
|
存储 SQL 人工智能
4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)
4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)
942 1
4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(三)
|
2月前
|
算法 关系型数据库 分布式数据库
0 PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本
背景PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力.本文将介绍PolarDB 开源版通过pg_similarity实现17种文本相似搜索...
62 0
|
存储 并行计算 算法
PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本.
PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力. 本文将介绍PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本.
516 0
|
SQL 存储 缓存
4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(一)
4 PostgreSQL 索引,全文检索,模糊匹配,近似度匹配(一)
195 0
|
存储 算法 关系型数据库
PostgreSQL 9.6 黑科技 bloom 算法索引,一个索引支撑任意列组合查询
bloom filter是一个有损过滤器,使用有限的比特位存储一些唯一值集合所产生的bits。通过这些bits可以满足这样的场景需求,给定一个值,判断这个值是否属于这个集合。例如 create table test(c1 int); insert into test select trunc
14126 0
|
SQL 自然语言处理 关系型数据库
PostgreSQL 如何高效解决 按任意字段分词检索的问题 - case 1
背景 在有些应用场景中,可能会涉及多个字段的匹配。 例如这样的场景,一张表包含了几个字段,分别为歌手,曲目,专辑名称,作曲,歌词, 。。。 用户可能要在所有的字段中以分词的方式匹配刘德华,任意字段匹配即返回TRUE。 传统的做法是每个字段建立分词索引,然后挨个匹配。
8980 0