我有两个分区表,它们具有类似的范围分区(其中DATE_KEY是整数形式的日期--比如9月1日的20230901,例如:

create table header (
   date_key int,
   header_key bigint,
   other_header_fields character varying(255),
   constraint pk_header primary key (date_key, header_key)
) partition by range (date_key);

create table detail (
   date_key int,
   header_key bigint,
   detail_key bigint,
   other_detail_fields character varying(255), -- [. . .] more fields
   constraint pk_detail primary key (date_key, header_key, detail_key)
) partition by range (date_key);

分区设置为每月范围(即:

create table header_p20230900 partition of header
   for values from (20230900) to (20231000);

这些表在组合视图中使用,如下所示:

create view v_record_details as
select 
   d.date_key,
   h.header_key,
   h.other_header_fields,
   d.detail_key,
   d.other_detail_fields
from detail       d
inner join header h on d.date_key = h.date_key and d.header_key = h.header_key;

当我从该视图中 Select 时,执行计划本身并不仅限于两个表中所需的分区:

select * 
from v_record_details
where date_key = 20230901;

这将限制细节表的分区(可能是因为我从细节表中 Select 了DATE_KEY);但是,在对已分区表进行索引扫描之前,它会对Header表中的所有分区执行seq扫描.

我似乎想不出如何让视图只访问所需的单个分区.有没有办法走出这种困境,而不需要一些愚蠢的东西,比如在两个表中都包含DATE_KEY,并期望用户在两个字段上都设置标准?

我已try 修改该视图以将where h.date_key = d.date_key包含在该视图中,但没有任何影响.

我还try 在视图的SELECT语句中设置显式条件--当视图的SELECT语句直接使用条件执行时(即:

select 
   d.date_key,
   h.header_key,
   h.other_header_fields,
   d.detail_key,
   d.other_detail_fields
from detail       d
inner join header h on d.date_key = h.date_key and d.header_key = h.header_key
where d.date_key = 20230901;

...行为如预期的那样,并且执行计划仅包括来自每个表的正确分区.

只有当写成一种观点时,执行计划才是错误的.

最新情况: 根据Richard Huxton的 comments ,我重新测试并发现,当视图中的SELECT查询在WHERE语句中使用=时,问题并没有如上所述地发生.只有在try 对一系列日期设置标准时,才会发生这种情况,例如:

select *
from v_record_details
where d.date_key between 20230901 and 20230930

In that case, the select statement itself has the same problem as the view, it is scanning to access all partitions from the header table. Plan Analysis

推荐答案

您没有共享整个查询计划,但我得到了类似的结果:其中一个表的分区修剪在使用between(在我的例子中是在表detail上)时工作得很好,但在另一个表上就不行了.

当我将configurationenable_partitionwise_join更改为on时,两个表都从分区修剪中受益.默认值(至少在版本16之前的所有版本中)为off.

SHOW enable_partitionwise_join;

SET enable_partitionwise_join TO on;

EXPLAIN __your_query__;

当一切正常时:

ALTER SYSTEM SET enable_partitionwise_join TO on; -- superuser needed

SELECT pg_reload_conf(); -- superuser needed

Sql相关问答推荐

SQL Google Sheets:UNIQUE/DISTINCT和编码查询函数

将主表与历史表连接以获取主表的当前汇率以及历史表中的上一个和最后一个汇率

SQL子查询返回多个值错误

使用列表作为参数进行 Select ,如果为空,则在PostgreSQL中不使用参数进行 Select

两个不同星期的销售额,不加成一行

在Athena中使用regexp提取括号前的字符串值

删除对 JSON 数据的未解析引用的 SQL71502 警告

JSON对象查询SQL服务器

达到特定值时,从0开始累加求和

每个ID的SQL返回可能的最低级别及其值

基于 Snowflake 的最大值创建新列

SQL获取两个日期范围之间的计数

Clob 问题 - 将 clob 列拆分为多行

Select 字段,除非另一个字段包含重复项

计算 PostgreSQL 中的平均会话长度

在 postgresql 中,我可以将其组合成一个查询吗?

基于源表的 SQL INSERT、UPDATE 和 DELETE

超过100名员工的连续行

如何计算每行出现的次数并显示在另一个表中?

如何在 RavenDB Studio (RQL) 中插入更新文档