首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用范围条件(>=、<=或介于之间)时,Postgres条件下推

使用范围条件(>=、<=或介于之间)时,Postgres条件下推
EN

Database Administration用户
提问于 2021-05-12 08:09:33
回答 1查看 182关注 0票数 2

我想更好地理解Postgres查询执行器将条件推入连接组件的情况。我将特别感谢对此负责的源代码部分的引用。

假设您有一个视图,其中的主体是日期字段上两个表之间的连接,如下所示(这是一个简单的虚构示例,没有真实的解释):

模式(PostgreSQL v13)

代码语言:javascript
复制
create table measures (mdate date, measurement numeric);
create index measures_mdate on measures(mdate);

create view name_matches_surname as 
   select m1.*, m2.measurement as the_other_measurement 
   from measures m1 left join measures m2 on (m1.mdate = m2.mdate);
            
insert into measures values ('2021-05-11',1.0), ('2021-05-11',2.0);

如果我在此视图中选择日期字段中的相等条件,则该条件将向下推到联接的两边,如下所示:

查询#1:(= 'now')按下

代码语言:javascript
复制
explain select * from name_matches_surname where mdate='now'::date;
代码语言:javascript
复制
| QUERY PLAN                                                                              |
| --------------------------------------------------------------------------------------- |
| Nested Loop Left Join  (cost=8.40..27.89 rows=36 width=68)                              |
|   Join Filter: (m1.mdate = m2.mdate)                                                    |
|   ->  Bitmap Heap Scan on measures m1  (cost=4.20..13.67 rows=6 width=36)               |
|         Recheck Cond: (mdate = '2021-05-12'::date)                                      |
|         ->  Bitmap Index Scan on measures_mdate  (cost=0.00..4.20 rows=6 width=0)       |
|               Index Cond: (mdate = '2021-05-12'::date)                                  |
|   ->  Materialize  (cost=4.20..13.70 rows=6 width=36)                                   |
|         ->  Bitmap Heap Scan on measures m2  (cost=4.20..13.67 rows=6 width=36)         |
|               Recheck Cond: (mdate = '2021-05-12'::date)                                |
|               ->  Bitmap Index Scan on measures_mdate  (cost=0.00..4.20 rows=6 width=0) |
|                     Index Cond: (mdate = '2021-05-12'::date)                            |

如您所见,连接的两边都是索引扫描,使用条件(='now')访问索引。到目前一切尚好。让我们尝试范围条件(介于),而不是:

查询#2:将中间部分推入连接的一侧--仅

代码语言:javascript
复制
explain select * from name_matches_surname 
  where mdate between 'now'::date-5 and 'now'::date;
代码语言:javascript
复制
| QUERY PLAN                                                                                        |
| ------------------------------------------------------------------------------------------------- |
| Hash Right Join  (cost=13.77..41.61 rows=38 width=68)                                             |
|   Hash Cond: (m2.mdate = m1.mdate)                                                                |
|   ->  Seq Scan on measures m2  (cost=0.00..22.70 rows=1270 width=36)                              |
|   ->  Hash  (cost=13.70..13.70 rows=6 width=36)                                                   |
|         ->  Bitmap Heap Scan on measures m1  (cost=4.21..13.70 rows=6 width=36)                   |
|               Recheck Cond: ((mdate >= '2021-05-07'::date) AND (mdate <= '2021-05-12'::date))     |
|               ->  Bitmap Index Scan on measures_mdate  (cost=0.00..4.21 rows=6 width=0)           |
|                     Index Cond: ((mdate >= '2021-05-07'::date) AND (mdate <= '2021-05-12'::date)) |

正如您所看到的,中间被推倒到连接的左侧,而对于右侧,我们进行了Seq扫描。您可以很容易地验证连接类型(内或左)或表的大小对下推结果没有影响-条件不会向下推到连接的右侧。

据我所见,这种行为在Postgres 9.5和13之间的所有版本中都是一致的。

原因是什么?是否有可能以一种不同的方式重写视图,以便“同样好”地推倒视图之间的关系,比如()?是否有对文档或源代码的引用,以深入解释下推策略?

关于DB Fiddle的看法

EN

回答 1

Database Administration用户

发布于 2021-05-12 16:33:06

使用=,优化器可以推断,如果m1.mdate = m2.mdatem1.mdate = 'constant',则对于m2.mdate也必须保持相同的条件。对于不等式运算符则不存在这样的推论。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/291421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档