ok, partitioning - Can PostgreSQL 12 do partition pruning at execution time with subquery returning a list? - Stack Overflow <https://stackoverflow.com/questions/61111395/can-postgresql-12-do-partition-pruning-at-execution-time-with-subquery-returning>
ok forcing hash join off, did not work as the outer table was the partitioned table selected. On Tue, 11 May 2021 at 22:42, Vijaykumar Jain < vijaykumarjain.git...@gmail.com> wrote: > Ok. maybe you are in a rush. > > But I would keep the thread open, to understand what I am not > understanding or else, it'll become a habit of converting sql to plpgsql :) > > Big Guys, > It seems, when the table is partitioned by range, it makes use of a nested > loop which helps in partition pruning. > if the table is list partitioned, it scans all the partitions. > > Is this expected ? > > > > LIST BASED PARTITION > ********************** > postgres@go:~$ more p.sql > drop table tbl1; > drop table tprt; > > create table tbl1(col1 int); > insert into tbl1 values (501), (505); > > -- Basic table > create table tprt (col1 int) partition by list (col1); > create table tprt_1 partition of tprt for values in (501); > create table tprt_2 partition of tprt for values in (1001); > create table tprt_3 partition of tprt for values in (2001); > create table tprt_4 partition of tprt for values in (3001); > create table tprt_5 partition of tprt for values in (4001); > create table tprt_6 partition of tprt for values in (5001); > > create index tprt1_idx on tprt_1 (col1); > create index tprt2_idx on tprt_2 (col1); > create index tprt3_idx on tprt_3 (col1); > create index tprt4_idx on tprt_4 (col1); > create index tprt5_idx on tprt_5 (col1); > create index tprt6_idx on tprt_6 (col1); > > insert into tprt values (501), (1001), (2001), (3001), (4001), (5001), > (501); > > alter table tbl1 add column col2 int default 0; > update tbl1 set col2 =1 where col1 = 501; > > vacuum analyze tprt; > vacuum analyze tbl1; > > explain analyze select * from tprt where tprt.col1 in (select tbl1.col1 > from tbl1 where tbl1.col2 in (1, 2) ); > > QUERY PLAN > > ------------------------------------------------------------------------------------------------------------ > Hash Semi Join (cost=1.05..7.20 rows=2 width=4) (actual > time=0.028..0.034 rows=2 loops=1) > Hash Cond: (tprt.col1 = tbl1.col1) > -> Append (cost=0.00..6.10 rows=7 width=4) (actual time=0.003..0.008 > rows=7 loops=1) > -> Seq Scan on tprt_1 (cost=0.00..1.02 rows=2 width=4) (actual > time=0.002..0.003 rows=2 loops=1) > -> Seq Scan on tprt_2 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_3 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_4 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.000..0.000 rows=1 loops=1) > -> Seq Scan on tprt_5 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_6 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Hash (cost=1.02..1.02 rows=2 width=4) (actual time=0.006..0.006 > rows=1 loops=1) > Buckets: 1024 Batches: 1 Memory Usage: 9kB > -> Seq Scan on tbl1 (cost=0.00..1.02 rows=2 width=4) (actual > time=0.003..0.003 rows=1 loops=1) > Filter: (col2 = ANY ('{1,2}'::integer[])) > Rows Removed by Filter: 1 > Planning Time: 0.237 ms > Execution Time: 0.060 ms > > > *even if i set hashjoin off* > > postgres=# set enable_hashjoin TO 0; > SET > postgres=# explain analyze select * from tprt where tprt.col1 in (select > tbl1.col1 from tbl1 where tbl1.col2 in (1, 2) ); > QUERY PLAN > > ------------------------------------------------------------------------------------------------------------ > Nested Loop Semi Join (cost=0.00..7.34 rows=2 width=4) (actual > time=0.013..0.023 rows=2 loops=1) > Join Filter: (tprt.col1 = tbl1.col1) > Rows Removed by Join Filter: 5 > -> Append (cost=0.00..6.10 rows=7 width=4) (actual time=0.004..0.010 > rows=7 loops=1) > -> Seq Scan on tprt_1 (cost=0.00..1.02 rows=2 width=4) (actual > time=0.003..0.003 rows=2 loops=1) > -> Seq Scan on tprt_2 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_3 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_4 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_5 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Seq Scan on tprt_6 (cost=0.00..1.01 rows=1 width=4) (actual > time=0.001..0.001 rows=1 loops=1) > -> Materialize (cost=0.00..1.03 rows=2 width=4) (actual > time=0.001..0.001 rows=1 loops=7) > -> Seq Scan on tbl1 (cost=0.00..1.02 rows=2 width=4) (actual > time=0.007..0.007 rows=1 loops=1) > Filter: (col2 = ANY ('{1,2}'::integer[])) > Rows Removed by Filter: 1 > Planning Time: 0.578 ms > Execution Time: 0.038 ms > (16 rows) > > ********************** > > > > RANGE BASED PARTITION > ********************** > postgres@go:~$ more q.sql > drop table tbl1; > drop table tprt; > create table tbl1(col1 int); > insert into tbl1 values (501), (505); > > -- Basic table > create table tprt (col1 int) partition by range(col1); > create table tprt_1 partition of tprt for values from (0) to (500); > create table tprt_2 partition of tprt for values from (500) to (1000); > create table tprt_3 partition of tprt for values from (1000) to (1500); > create table tprt_4 partition of tprt for values from (1500) to (2000); > create table tprt_5 partition of tprt for values from (2000) to (22500); > > create index tprt1_idx on tprt_1 (col1); > create index tprt2_idx on tprt_2 (col1); > create index tprt3_idx on tprt_3 (col1); > create index tprt4_idx on tprt_4 (col1); > create index tprt5_idx on tprt_5 (col1); > > insert into tprt values (501), (1001), (2001), (3001), (4001), (5001), > (501); > > vacuum analyze tbl1; > vacuum analyze tprt; > > alter table tbl1 add column col2 int default 0; > update tbl1 set col2 =1 where col1 = 501; > > explain analyze select * from tprt where tprt.col1 in (select tbl1.col1 > from tbl1 where tbl1.col2 in (1, 2) ); > > QUERY PLAN > > ---------------------------------------------------------------------------------------------------------------- > Nested Loop (cost=3.29..55.37 rows=2 width=4) (actual time=0.016..0.018 > rows=2 loops=1) > -> Unique (cost=1.03..1.04 rows=2 width=4) (actual time=0.012..0.012 > rows=1 loops=1) > -> Sort (cost=1.03..1.04 rows=2 width=4) (actual > time=0.011..0.011 rows=1 loops=1) > Sort Key: tbl1.col1 > Sort Method: quicksort Memory: 25kB > -> Seq Scan on tbl1 (cost=0.00..1.02 rows=2 width=4) > (actual time=0.004..0.005 rows=1 loops=1) > Filter: (col2 = ANY ('{1,2}'::integer[])) > Rows Removed by Filter: 1 > -> Append (cost=2.26..26.86 rows=30 width=4) (actual > time=0.003..0.004 rows=2 loops=1) > -> Bitmap Heap Scan on tprt_1 (cost=2.26..11.81 rows=13 > width=4) (never executed) > Recheck Cond: (col1 = tbl1.col1) > -> Bitmap Index Scan on tprt1_idx (cost=0.00..2.25 > rows=13 width=0) (never executed) > Index Cond: (col1 = tbl1.col1) > -> Seq Scan on tprt_2 (cost=0.00..1.02 rows=2 width=4) (actual > time=0.001..0.002 rows=2 loops=1) > Filter: (tbl1.col1 = col1) > -> Seq Scan on tprt_3 (cost=0.00..1.01 rows=1 width=4) (never > executed) > Filter: (tbl1.col1 = col1) > -> Bitmap Heap Scan on tprt_4 (cost=2.26..11.81 rows=13 > width=4) (never executed) > Recheck Cond: (col1 = tbl1.col1) > -> Bitmap Index Scan on tprt4_idx (cost=0.00..2.25 > rows=13 width=0) (never executed) > Index Cond: (col1 = tbl1.col1) > -> Seq Scan on tprt_5 (cost=0.00..1.05 rows=1 width=4) (never > executed) > Filter: (tbl1.col1 = col1) > Planning Time: 0.214 ms > Execution Time: 0.069 ms > (25 rows) > > ********************** > > > > > > > > > > > > > > > > On Tue, 11 May 2021 at 17:44, Niels Jespersen <n...@dst.dk> wrote: > >> > >> >> >Sorry, >> >> > >> >> >I made a major mistake. I somehow saw the period and period_version as >> the same. >> >> >so, yes partitions are not pruned here. So my suggestion makes no sense. >> >> >> >> Thats quite ok. I think my plan now is to have a table returning function >> that executes a query dynamically. The query has a where caluse that is >> first constructed. >> >> >> >> Like this: >> >> >> >> >> >> return query execute format('select d.x, d.y from %1$I.%1$I d where >> d.period_version = any(' || quote_literal(_periode_version_array) >> ||'::text[])', register_in); >> >> >> >> Regards Niels >> >> >> >> >> > > > -- > Thanks, > Vijay > Mumbai, India > -- Thanks, Vijay Mumbai, India