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

简介: 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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
存储 安全 关系型数据库
PostgreSQL物化视图增量更新扩展 -- pg_ivm
PostgreSQL不支持物化视图增量更新,需要定期执行REFRESH MATERIALIZED VIEW命令刷新物化视图。Incremental View Maintenance (IVM)是一种使物化视图保持最新的方法,其中只计算增量更改并将其应用于视图,而不是REFRESH MATERIALIZED VIEW那样从头开始重新计算内容。当只更改视图的一小部分时,IVM可以比重新计算更高效地更新物化视图。
|
缓存 监控 Linux
Linux 基础之 sar 工具详解
【2月更文挑战第12天】Linux 基础之 sar 工具详解
424 7
Linux 基础之 sar 工具详解
|
8月前
|
存储 关系型数据库 测试技术
拯救海量数据:PostgreSQL分区表性能优化实战手册(附压测对比)
本文深入解析PostgreSQL分区表的核心原理与优化策略,涵盖性能痛点、实战案例及压测对比。首先阐述分区表作为继承表+路由规则的逻辑封装,分析分区裁剪失效、全局索引膨胀和VACUUM堆积三大性能杀手,并通过电商订单表崩溃事件说明旧分区维护的重要性。接着提出四维设计法优化分区策略,包括时间范围分区黄金法则与自动化维护体系。同时对比局部索引与全局索引性能,展示后者在特定场景下的优势。进一步探讨并行查询优化、冷热数据分层存储及故障复盘,解决分区锁竞争问题。
1072 2
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
13827 60
|
2月前
|
缓存 NoSQL Redis
千万级数据表的count(*)查询优化
针对千万级数据表`user_factor_auth_record`的COUNT查询性能问题,可通过“避免实时计数、独立计数表、Redis缓存”三大方案优化。优先从业务层面取消总条数展示,减轻数据库压力;若需精确值,可借助事务维护独立计数表,或定时缓存至Redis,分摊开销、提升查询效率。
217 5
|
监控 Java Nacos
使用Spring Boot集成Nacos
通过上述步骤,Spring Boot应用可以成功集成Nacos,利用Nacos的服务发现和配置管理功能来提升微服务架构的灵活性和可维护性。通过这种集成,开发者可以更高效地管理和部署微服务。
4286 17
|
存储 SQL 缓存
聊聊性能,如何合理设置索引?
【6月更文挑战第1天】本文介绍了数据库索引过多的索引会使更新表的速度变慢,增大数据库体积和维护成本。索引过多的风险包括降低增删改操作性能、增大数据库体积、增加存储压力和维护开销,以及加大SQL Server优化开销。建议的核心表索引不超过7个,普通表不超过5个,小型表不超过3个。针对索引过多的问题,文章提出需要根据实际需求进行分析并提供解决方案。
650 4
聊聊性能,如何合理设置索引?
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
370 18
|
Cloud Native Java 物联网
NATS
【7月更文挑战第8天】
440 4
|
消息中间件 Shell 数据处理
rocket mq 查看消费进度,消息堆积,清除堆积数据命令
该内容是关于RocketMQ的消费进度管理和堆积数据处理的指导。首先,需进入RocketMQ的bin目录,然后使用`mqadmin consumerProgress`命令查看消费者或生产者的消费进度。`broker offset`和`consumer offset`的差值表示未消费消息。通过`resetOffsetByTime`命令可重置消费位点来清除堆积数据,未消费消息默认3天后会被丢弃。此外,`CONSUME_FROM WHERE`枚举类定义了消费起点选项,包括从最后、最开始或指定时间点消费。
4158 3