PostgreSQL17优化器改进(3)在使用包含操作符<@和@>时优化范围查询

server/2024/10/18 12:19:28/

PostgreSQL17优化器改进(3)在使用包含操作符<@和@>时优化范围查询

本文将介绍PostgreSQL 17服务端优化器在使用包含操作符<@和@>时优化范围查询。其实在在第一眼看到官网网站的对于该优化点的时候,可能是由于缺乏对于范围类型的认知,因此也不太清楚具体优化的场景,但是通过详细的阅读官网沟通邮件及官网文档,也基本搞明白了PostgreSQL17 的优化场景。下面是整理的功能测试用例及不支持的场景的测试用例。

创建测试用例需要的表

CREATE TABLE rang_integer (num integer);
insert into rang_integer  select generate_series(-100000, 100000);
CREATE index idx_rang_integer ON rang_integer( num );
ANALYZE rang_integer;

PostgreSQL16.3中的执行计划

在PostgreSQL16.3中,测试用例将对比BETWEEN and语句和范围操作符@>、@< 的执行计划和执行用时。

testdb=> EXPLAIN ANALYZE SELECT num FROM rang_integer WHERE num BETWEEN -10 AND 8;QUERY PLAN                                                              
--------------------------------------------------------------------------------------------------------------------------------------Index Only Scan using idx_rang_integer on rang_integer  (cost=0.42..4.80 rows=19 width=4) (actual time=0.470..0.475 rows=19 loops=1)Index Cond: ((num >= '-10'::integer) AND (num <= 8))Heap Fetches: 0Planning Time: 0.191 msExecution Time: 0.502 ms
(5 rows)Time: 1.721 ms
testdb=> 
testdb=> 
testdb=> EXPLAIN ANALYZE SELECT num FROM rang_integer WHERE num <@ int4range(-10, 8);QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------Seq Scan on rang_integer  (cost=0.00..3385.01 rows=1000 width=4) (actual time=17.626..36.529 rows=18 loops=1)Filter: (num <@ '[-10,8)'::int4range)Rows Removed by Filter: 199983Planning Time: 0.113 msExecution Time: 36.552 ms
(5 rows)Time: 37.285 ms

在PostgreSQL16.3版本中检查一个元素是否包含在一个范围中时,使用@>或<@操作符的性能比BETWEEN AND的查询性能都差且差距比较大;通过执行计划我们也可以看出,在使用范围操作符时,扫描方式使用的是Seq Scan on rang_integer ,未使用到范围过滤条件上的索引。

PostgreSQL17.0Beta 1中的执行计划

在PostgreSQL17中,同样测试用例将对比BETWEEN and语句和范围操作符@>、@< 的执行计划和执行用时。

testdb=> EXPLAIN ANALYZE SELECT num FROM rang_integer WHERE num BETWEEN -10 AND 8;QUERY PLAN                                                              
--------------------------------------------------------------------------------------------------------------------------------------Index Only Scan using idx_rang_integer on rang_integer  (cost=0.42..4.84 rows=21 width=4) (actual time=0.281..0.286 rows=19 loops=1)Index Cond: ((num >= '-10'::integer) AND (num <= 8))Heap Fetches: 0Planning Time: 0.192 msExecution Time: 0.315 ms
(5 rows)Time: 1.205 ms
testdb=> 
testdb=> ^C
testdb=> EXPLAIN ANALYZE SELECT num FROM rang_integer WHERE num <@ int4range(-10, 8);QUERY PLAN                                                              
--------------------------------------------------------------------------------------------------------------------------------------Index Only Scan using idx_rang_integer on rang_integer  (cost=0.42..4.82 rows=20 width=4) (actual time=0.034..0.039 rows=18 loops=1)Index Cond: ((num >= '-10'::integer) AND (num < 8))Heap Fetches: 0Planning Time: 0.207 msExecution Time: 0.061 ms
(5 rows)Time: 0.794 ms

在PostgreSQL17版本中,优化范围值的查询后,通过对比 PostgreSQL16.3和PostgreSQL17的范围操作符查询,执行耗时由原来的37.285ms降低到0.794 ms,执行SQL的耗时大概提升了40倍多。我们再查看PostgreSQL17版本中的执行计划,发现在使用范围操作符时过滤数据时,已经用到之前新建的索引idx_rang_integer,因此查询才得到了提升。

PostgreSQL17.0Beta 1中不支持的场景

检查可变用例是否优化

这些用例是官网文档中提供的,通过下面的测试可知,对于值可变的情况,未进行优化

testdb=> select now();now              
-------------------------------2024-06-11 17:06:07.074701+08
(1 row)Time: 0.331 ms
testdb=> explain (verbose, costs off)
testdb-> select now() <@ tstzrange('2024-06-10 00:00', '2024-06-20 00:00');QUERY PLAN                                                                 
--------------------------------------------------------------------------------------------------------------------------------------------ResultOutput: ((now() >= '2024-06-10 00:00:00+08'::timestamp with time zone) AND (now() < '2024-06-20 00:00:00+08'::timestamp with time zone))
(2 rows)Time: 0.610 ms
testdb=> explain (verbose, costs off)  -- unsafe!
testdb-> select clock_timestamp() <@ tstzrange('2024-06-10 00:00', '2024-06-20 00:00');QUERY PLAN                                             
---------------------------------------------------------------------------------------------------ResultOutput: (clock_timestamp() <@ '["2024-06-10 00:00:00+08","2024-06-20 00:00:00+08")'::tstzrange)
(2 rows)Time: 0.532 ms
testdb=> explain (verbose, costs off)
testdb-> select clock_timestamp() <@ tstzrange('2024-01-20 00:00', NULL);QUERY PLAN                                      
-------------------------------------------------------------------------------------ResultOutput: (clock_timestamp() >= '2024-01-20 00:00:00+08'::timestamp with time zone)
(2 rows)Time: 0.714 ms

总结

在PostgreSQL 17中为范围操作符<@和@>添加优化器支持函数,这些支持函数将优化具有恒定范围值的表达式转换为对范围边界值的直接比较,其实就是启用了过滤条件上的索引。但是,有些情况也是不支持的,如果对可变的或代价高的元素表达式进行双重求值,则跳过该转换。


http://www.ppmy.cn/server/48617.html

相关文章

redis序列化

文章目录 1、为什么要进行序列化操作&#xff1f;2、序列化方式2.1、自定义序列化2. 2、StringRedisTemplate&#xff08;重点&#xff09; 1、为什么要进行序列化操作&#xff1f; 不进行序列化向redis存入数据代码&#xff1a; SpringBootTest class RedisDemoApplicationT…

SQL Developer迁移第三方数据库单表到Oracle

在SQL Developer中&#xff0c;除可用Migration Wizard迁移第三方数据库到Oracle外&#xff0c;单表的迁移可以用Copy To Oracle ...菜单。右键单击源表即可。 本例的源表为MySQL数据库employees中的表&#xff1a;departments。 Options页面&#xff1a;指定目标库&#xff…

富格林:了解实情摆脱暗箱被骗

富格林悉知&#xff0c;就当下的投资市场看投资者一般会特别关注盈利效率高的产品&#xff0c;而近年来兴起的现货黄金恰恰就符合这个条件。不过新手投资者不了解市场实情&#xff0c;其实很难去判断和摆脱其中的暗箱而导致被骗。因此学会了解实情对于摆脱暗箱被骗极其重要&…

深度学习的点云检测

深度学习的点云检测 点云检测是计算机视觉和图形学中的一项重要任务&#xff0c;旨在识别和定位三维点云数据中的特定物体或区域。点云数据由大量三维点组成&#xff0c;每个点包含空间坐标&#xff08;x, y, z&#xff09;&#xff0c;有时还包含颜色、法向量等附加信息。点云…

Django 里实现表格内容上传

先看效果图&#xff1a; 当没有添加数据&#xff0c;就按 提交 键就会出现报错 下面是操作步骤 1. 先在 views.py 文件里做添加 # 在 views.py class AssetModelForm(forms.ModelForm):#newField forms.CharField()class Meta:model models.AssetSet fields [name, pri…

b站视频下载到电脑本地mp4格式,b站视频下载到手机相册

有时候我们想把网站上的视频下载到电脑或手机&#xff0c;其实有多种方法可供选择。本文将详细介绍几种常见的下载方式&#xff0c;并探讨它们的优缺点&#xff0c;帮助读者根据自己的需求选择最适合的下载方法。 方法一&#xff1a; 1、使用 "小白兔视频格式在线转换网站…

诺派克ROPEX控制器维修RES-5008 RES-5006

德国希尔科诺派克ROPEX热封控制器维修型号包括&#xff1a;RES-401&#xff0c;RES-402&#xff0c;RES-403&#xff0c;RES-406&#xff0c;RES-407&#xff0c;RES-408&#xff0c;RES-409&#xff0c;RES-420&#xff0c;RES-440&#xff0c;RES-5008&#xff0c;RES-5006&a…

栈(Stack)汇总

栈简介 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或者删除操作的线性表。它的操作特性可以概括为——后进先出&#xff08;Last In First Out&#xff0c;LIFO&#xff09;。栈顶&#xff08;Top&#xff09;——线性表允许进行插入删除的一端&#xff1b; 栈底…