Let us suppose that I have a table
d_day
containing two columns, id_day
, and date
, and a table fact
that contains two columns, id_day
and fact
. My table fact
is partitioned across id_day
.
The request
SELECT * FROM fact
WHERE "ID_DAY" between and
is pruning partitions properly, and is almost instant but
SELECT * FROM fact
INNER JOIN d_dat USING (id_day)
WHERE date between and
is not. I have a UNIQUE constraint over date
in my d_day
column. So, I have a 1:1 relationship between the two columns.
On a broader level, I do not understand how the query planner deals with this demand.
Even something like :
SELECT * FROM fact
WHERE id_day IN (
SELECT DISTINCT(id_day) WHERE date BETWEEN and
)
is slow.
Here is a practical example when filtering on DATEJ:
set enable_partitionwise_join = true; set enable_partitionwise_aggregate = true;
EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)(
select * from "F_TDOJ_HIST_2" fth
inner join "D_TRAIN" dt using ("ID_TRAIN")
inner join "DL_CAPTURE_DATE" dj using ("ID_JOUR", "JX")
where "JX" = -72
and "ID_ENTNAT" between 4000 and 4999
and "DATEJ" = '2023-12-08'::date);
(Explain analyze )
And here is the example when filtering on ID_JOUR
set enable_partitionwise_join = true; set enable_partitionwise_aggregate = true;
EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)(
select * from "F_TDOJ_HIST_2" fth
inner join "D_TRAIN" dt using ("ID_TRAIN")
inner join "DL_CAPTURE_DATE" dj using ("ID_JOUR", "JX")
where "JX" = -72
and "ID_ENTNAT" between 4000 and 4999
and "ID_JOUR" = 4756);
(Explain analyze )
Also, when I play the request using DATEJ on a copy of my database, partitioned across a different ID_JOUR span (30 ID_JOUR in a partition vs 3 ID_JOUR) now, I get this plan, which is **much faster**, so I know doing something is possible. I just do not understand why it is now slower, what to change, and why :
set enable_partitionwise_join = true; set enable_partitionwise_aggregate = true;
EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)(
select * from "F_TDOJ_HIST_2" fth
inner join "D_TRAIN" dt using ("ID_TRAIN")
inner join "DL_CAPTURE_DATE" dj using ("ID_JOUR", "JX")
where "JX" = -72
and "ID_ENTNAT" between 4000 and 4999
and "DATEJ" = '2023-12-08'::date);
(Explain analyze )
Asked by Doe Jowns
(141 rep)
Oct 19, 2023, 02:19 PM
Last activity: May 9, 2025, 08:02 AM
Last activity: May 9, 2025, 08:02 AM