Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v3HAA-00DqhM-Qw for pgsql-performance@arkaria.postgresql.org; Mon, 29 Sep 2025 16:55:47 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1v3HA7-002uPk-Nt for pgsql-performance@arkaria.postgresql.org; Mon, 29 Sep 2025 16:55:44 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v3EGH-001JzA-KI for pgsql-performance@lists.postgresql.org; Mon, 29 Sep 2025 13:49:54 +0000 Received: from mail-vs1-xe35.google.com ([2607:f8b0:4864:20::e35]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1v3EGC-000VvC-1M for Pgsql-performance@postgresql.org; Mon, 29 Sep 2025 13:49:53 +0000 Received: by mail-vs1-xe35.google.com with SMTP id ada2fe7eead31-59dff155dc6so2994646137.3 for ; Mon, 29 Sep 2025 06:49:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1759153787; x=1759758587; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=99chiIOCeQGEd/Ekp61OjYLbDK3oWI4rDIxP4NU33LE=; b=OG2pxio1yPZjIUgwMw5zCEYlvZhYz7qH9hIBNJYBtnKkYLVGVMT6gGZ9TqyklsAb63 jKO7Zrqyq4HkYrcsQoTCcaa0kppS07L/DSwf1UJHCBv2KGcVsf3a0wWUJzSHX7lKMCe1 fXDDk6BFTUW/kdGDf7uBJ5NmvgVrj9Ub+VQAVUL9L/HRpBkNu5NO7IlmQ8ehYqL7bCKI fP31YkQx+Bu0qxNoPc+SS/ibS0W20xjpW+pK9HWYU98fvCeDpy0jsRhtiJwrAPIwTHk6 FajfzyhzFVtLH85eHrviAqi2EH5jGQdGmbv5ETtOIEmdILaHEqvq9EWhy5QJuNzCjBl1 q7nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759153787; x=1759758587; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=99chiIOCeQGEd/Ekp61OjYLbDK3oWI4rDIxP4NU33LE=; b=LZGGMZ1HUiiSRI9jFz+ynGiuReFx0/0LW58EB/A1oAWH8cwGBBCpaXXSEKL9XCuuHn IBfCqWugLu/RJO4kbPFaR0t+M4MTkDbzkKqGT0C++3Gtc5lagjvvEieOHU410qwpMdck rn0nQ58aYrAyyqdgI4gKrhVlrReDr+dtxYX3S6ofJVmRMrbDxn1hloY5VyQ7hLRuqnd8 9vZJgyzkWqFPIORJe/tdqn7Qp7FJok0NeI42dHpvAe22OaPV+ikqml7kOYGegiLor08Z 08Qgt2qSE4PIJjSg0RoQVhb0xT4iZ12mFBXENnbjWl8kmy/SNfTtaX02e3nY9R0Hvf/y AWnw== X-Gm-Message-State: AOJu0YwrVKNYcV1MbVbPIITZbtG5td3lVTTQh/wybkMP6IDbXDnBZEmY YmIBb96WxKfJiYcNontYhCnMZQ6rzJermUOX3pLUS00GwJ1/TBl/NT3Sm9+qXE6xirP/A9y5Pxk uvUxWkPa1rECnXWiiybZMWvaToyR0Q7BaRgS5eXIy0w== X-Gm-Gg: ASbGnct5T/3VObDQPMJYQIpzNFa0vBEp5IvEn4be76ggPO+mjmzOHDGQC21jGw09ojS 9Ie2i4cC/AAw2ybwViVXNFngZ9p4updL85VAMkj9FF8e9KjxiGiU4hWcbBvJdEOsSVfGOyLRXMU P4Mcg++fljmcbToLFDcHgkE/FS6zQY9m2tNKdO1C33TOiiKilymm+KBOT8iaZeRw8+I312YRKVO kGbvQ== X-Google-Smtp-Source: AGHT+IFdBvaXdGVZzt187fuJnI735b9IvBXkOwPejPaYxjlx7IQVK5xp1p4Ri1tdoVfl4WmljjxQyd6PV3XSqmbFATM= X-Received: by 2002:a05:6102:50a0:b0:5a4:138d:b13c with SMTP id ada2fe7eead31-5acd2b17270mr6215784137.29.1759153787356; Mon, 29 Sep 2025 06:49:47 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Lauro Ojeda Date: Mon, 29 Sep 2025 15:49:31 +0200 X-Gm-Features: AS18NWAMfBsxgCVLKcX5dEf6OhuD3YiNNMHuSLS71NDNTALbFtOxyZ4MwI7v3L8 Message-ID: Subject: Re: Partition pruning is not happening (even in PG18) To: David Rowley Cc: Pgsql-performance@postgresql.org Content-Type: multipart/alternative; boundary="00000000000099cb5b063ff0e804" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000099cb5b063ff0e804 Content-Type: text/plain; charset="UTF-8" Hi David, Thank you for your nice reply. I have the impression there is something heavily penalizing the usage of partition pruning. While trying to go a bit further, I realized that partition pruning is not occurring because the planner gives the cost of seq-scanning all partitions to just over 2M units, but the query takes over 3 minutes. When forcing the usage of PK index via hinting (which down the line forces the partition pruning to happen), the cost sky-rocket to 53M units (however scanning 4 partitions out of 12). Even though with much higher cost, the query launches less workers and completes in a third (or less) of the time of all partition scans. My observation is that the cost of seq-scanning each partition is estimated in ~124k units, but index-scanning each partition is 440k (say, 3x higher). Therefore, scanning 4 partitions, the total cost should be ~1.7M units, which is below the 2M units from the cost of all partition scanning, thus the planner should prefer the indexed path instead. However when analyzing the hinted query (doing index scan and thus partition pruning) we can note that the cost estimated to each partition scan was added to the final cost, even though 8 out of 12 partitions were not scanned (never executed). postgres=> explain analyze /*+ IndexScan(accounts accounts_pkey) */ select aid, abalance from accounts where transaction_date in (select dt_col from t2); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop (cost=1.56..53359847.63 rows=2767123 width=8) (actual time=2.299..111346.649 rows=1664742 loops=1) -> HashAggregate (cost=1.12..1.23 rows=10 width=4) (actual time=1.060..40.562 rows=6 loops=1) Group Key: t2.dt_col Batches: 1 Memory Usage: 24kB -> Seq Scan on t2 (cost=0.00..1.10 rows=10 width=4) (actual time=1.048..1.050 rows=6 loops=1) -> Append (cost=0.43..5302777.61 rows=3320703 width=12) (actual time=1.554..18514.181 rows=277457 loops=6) -> Index Scan using accounts_p1_pkey on accounts_p1 accounts_1 (cost=0.43..434635.82 rows=273011 width=12) (actual time=2.214..17627.113 rows=276971 loops=1) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p2_pkey on accounts_p2 accounts_2 (cost=0.43..441097.44 rows=277283 width=12) (actual time=2.185..16280.020 rows=276634 loops=1) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p3_pkey on accounts_p3 accounts_3 (cost=0.43..441666.94 rows=277392 width=12) (actual time=0.751..25992.220 rows=278390 loops=1) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p4_pkey on accounts_p4 accounts_4 (cost=0.43..441689.70 rows=277483 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p5_pkey on accounts_p5 accounts_5 (cost=0.43..441883.26 rows=277546 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p6_pkey on accounts_p6 accounts_6 (cost=0.43..*441857.26 *rows=277591 width=12) (actual time=1.376..17001.777 rows=277582 loops=3) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p7_pkey on accounts_p7 accounts_7 (cost=0.43..441837.57 rows=277503 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p8_pkey on accounts_p8 accounts_8 (cost=0.43..441843.95 rows=277511 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p9_pkey on accounts_p9 accounts_9 (cost=0.43..441711.03 rows=277506 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p10_pkey on accounts_p10 accounts_10 (cost=0.43..441918.96 rows=277554 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p11_pkey on accounts_p11 accounts_11 (cost=0.43..441501.86 rows=277377 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) -> Index Scan using accounts_p12_pkey on accounts_p12 accounts_12 (cost=0.43..434530.31 rows=272946 width=12) (never executed) Index Cond: (transaction_date = t2.dt_col) Planning Time: 0.879 ms Execution Time: 111432.755 ms (32 rows) By looking into it, I have the impression there is a bug in the costing sum in that situation, where the cost of the "never executed" partitions should be deducted from the final cost estimation, which would make pruning to be the preferred option in this case. Are my assumptions correct? Is there anything I could do to influence the planner to dismiss the cost of "never executed" scans? Kind regards, Lauro Ojeda On Thu, 25 Sept 2025 at 22:18, David Rowley wrote: > On Fri, 26 Sept 2025 at 07:49, Lauro Ojeda wrote: > > The only way I found to make pruning work is to force index_scan using > pg_hint_plan, but I wanted to influence the planner to decide it by itself > rather than relying on hints. What's the reason for this misbehaving and > what could I do to overcome it? > > > Partition key: RANGE (transaction_date) > > > postgres=> explain analyze > > select aid, abalance > > from accounts > > where transaction_date in (select dt_col from t2); > > The only partition pruning that exists in PostgreSQL that can prune > for that query is for parameterised Nested Loop joins. For Hash Join, > it's been talked about, but this requires running the partition > pruning code for every values that goes into the Hash Table and only > scanning the unioned set of those partitions during the hash probe > phase. The trouble with that is that it's very hard to know in advance > if it'll be worth the extra effort. Putting a tuple into a hash table > is quite cheap. Running the pruning code for a range partitioned table > is likely to be a few times more costly than the hash insert > (depending on how many partitions there are), so if the end result is > that nothing was pruned, then that's quite a bit of extra effort for > no gain. > > What we maybe could do better is reduce the cost of the Append scan > when there's a run-time pruning object attached. This is a little > tricky as we currently only build that object when creating the final > plan. To include that in the costs we'd need to move that to the Path > generation phase so that we didn't accidentally reject Paths which > could be cheaper than we first think. > > > Also, how could I contribute to get this partition pruning to work? > > The pgsql-hackers mailing list is where all the discussions about that > happen. There is plenty of past discussions on these topics. One such > (fairly) recent discussion is in [1]. There are plenty more, including > some ideas from Robert Haas about how we might cost run-time partition > pruning. That was likely around 2017-2018 range, so you might need to > dig deep to find that. > > David > > [1] > https://www.postgresql.org/message-id/flat/CAApHDvoC7n_oceb%3D8z%2BMY8sTgH4xa%2ByAwBxZ4Dxv8pwkT9bOcA%40mail.gmail.com#45314d3d01ef8ad1eebe72111989062c > -- *Lauro Ojeda* --00000000000099cb5b063ff0e804 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi David,
Thank you for your nice reply.
I have the impression there is something heavily penalizing the= usage of partition pruning. While trying to go a bit further, I realized t= hat partition pruning is not occurring=C2=A0because the planner gives the c= ost of seq-scanning all partitions to just over 2M units, but the query tak= es over 3 minutes. When forcing the usage of PK index via hinting (which do= wn the line forces the partition pruning to happen), the cost sky-rocket to= 53M units=C2=A0(however scanning 4 partitions out of 12).=C2=A0Even though= with much higher cost, the query launches less workers and completes in a = third (or less) of the time of all partition scans.

My observ= ation is that the cost of seq-scanning each partition is estimated in ~124k= units, but index-scanning each partition is 440k (say, 3x higher). Therefo= re, scanning 4 partitions, the total cost should be ~1.7M units, which is b= elow the 2M units from the cost of all partition scanning, thus the planner= should prefer the indexed path instead. However when analyzing the hinted= =C2=A0query (doing index scan and thus partition pruning) we can note that = the cost estimated to each partition scan was added to the final cost, even= though 8 out of 12 partitions were not scanned (never executed).

postgres=3D> explain analyze
/*+ IndexS= can(accounts accounts_pkey) */
select aid, abalance
from accounts
= where transaction_date in (select dt_col from t2);
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0QUERY PLAN
-----------------------= ---------------------------------------------------------------------------= -----------------------------------------------------------------------
= =C2=A0Nested Loop =C2=A0(cost=3D1.56..53359847.63 <= /font>rows=3D2767123 width=3D8) (actual time=3D2.299..111346.649 rows=3D166= 4742 loops=3D1)
=C2=A0 =C2=A0-> =C2=A0HashAggregate =C2=A0(cost=3D1.1= 2..1.23 rows=3D10 width=3D4) (actual time=3D1.060..40.562 rows=3D6 loops=3D= 1)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Group Key: t2.dt_col
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0Batches: 1 =C2=A0Memory Usage: 24kB
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Seq Scan on t2 =C2=A0(cost=3D0.00..1.10= rows=3D10 width=3D4) (actual time=3D1.048..1.050 rows=3D6 loops=3D1)
= =C2=A0 =C2=A0-> =C2=A0Append =C2=A0(cost=3D0.43..5302777.61 rows=3D33207= 03 width=3D12) (actual time=3D1.554..18514.181 rows=3D277457 loops=3D6)
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts_p1_= pkey on accounts_p1 accounts_1 =C2=A0(cost=3D0.43..= 434635.82 rows=3D273011 width=3D12) (actual time=3D2.214..17627.113 = rows=3D276971 loops=3D1)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts_p2_pkey on accounts_= p2 accounts_2 =C2=A0(cost=3D0.43..441097.44 = rows=3D277283 width=3D12) (actual time=3D2.185..16280.020 rows=3D276634 loo= ps=3D1)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Con= d: (transaction_date =3D t2.dt_col)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-&= gt; =C2=A0Index Scan using accounts_p3_pkey on accounts_p3 accounts_3 =C2= =A0(cost=3D0.43..441666.94 rows=3D277392 wid= th=3D12) (actual time=3D0.751..25992.220 rows=3D278390 loops=3D1)
=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_d= ate =3D t2.dt_col)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index S= can using accounts_p4_pkey on accounts_p4 accounts_4 =C2=A0(cost=3D0.43..44= 1689.70 rows=3D277483 width=3D12) (never executed)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_c= ol)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accou= nts_p5_pkey on accounts_p5 accounts_5 =C2=A0(cost=3D0.43..441883.26 rows=3D= 277546 width=3D12) (never executed)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts_p6_pkey on= accounts_p6 accounts_6 =C2=A0(cost=3D0.43..4418= 57.26 rows=3D277591 width=3D12) (actual time=3D1.376..17001.777 = rows=3D277582 loops=3D3)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts_p7_pkey on accounts_= p7 accounts_7 =C2=A0(cost=3D0.43..441837.57 rows=3D277503 width=3D12) (neve= r executed)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index= Cond: (transaction_date =3D t2.dt_col)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0-> =C2=A0Index Scan using accounts_p8_pkey on accounts_p8 accounts_8 = =C2=A0(cost=3D0.43..441843.95 rows=3D277511 width=3D12) (never executed)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Cond: (transa= ction_date =3D t2.dt_col)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0= Index Scan using accounts_p9_pkey on accounts_p9 accounts_9 =C2=A0(cost=3D0= .43..441711.03 rows=3D277506 width=3D12) (never executed)
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_date =3D = t2.dt_col)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan usin= g accounts_p10_pkey on accounts_p10 accounts_10 =C2=A0(cost=3D0.43..441918.= 96 rows=3D277554 width=3D12) (never executed)
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts= _p11_pkey on accounts_p11 accounts_11 =C2=A0(cost=3D0.43..441501.86 rows=3D= 277377 width=3D12) (never executed)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Index Scan using accounts_p12_pkey o= n accounts_p12 accounts_12 =C2=A0(cost=3D0.43..434530.31 rows=3D272946 widt= h=3D12) (never executed)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Index Cond: (transaction_date =3D t2.dt_col)
=C2=A0Planning Ti= me: 0.879 ms
=C2=A0Execution Time: 111432.755 ms
(32 rows)

=
By looking into it, I have the impression there is a bug in = the costing sum in that situation, where the cost of the "never execut= ed" partitions should be deducted from the final cost estimation, whic= h would make pruning to be the preferred option in this case.
Are my assumptions correct?=C2=A0
Is there anything I could = do to influence the planner to dismiss the cost of "never executed&quo= t; scans?

Kind regards,
Lauro Ojeda
=C2=A0=C2=A0

On Thu, 25 Sept 2025 at 22:18= , David Rowley <dgrowleyml@gmail= .com> wrote:
On Fri, 26 Sept 2025 at 07:49, Lauro Ojeda <lauro.ojeda@gmail.com> wrote:
> The only way I found to make pruning work is to force index_scan using= pg_hint_plan, but I wanted to influence the planner to decide it by itself= rather than relying on hints. What's the reason for this misbehaving a= nd what could I do to overcome it?

> Partition key: RANGE (transaction_date)

> postgres=3D> explain analyze
> select aid, abalance
> from accounts
> where transaction_date in (select dt_col from t2);

The only partition pruning that exists in PostgreSQL that can prune
for that query is for parameterised Nested Loop joins.=C2=A0 For Hash Join,=
it's been talked about, but this requires running the partition
pruning code for every values that goes into the Hash Table and only
scanning the unioned set of those partitions during the hash probe
phase. The trouble with that is that it's very hard to know in advance<= br> if it'll be worth the extra effort. Putting a tuple into a hash table is quite cheap. Running the pruning code for a range partitioned table
is likely to be a few times more costly than the hash insert
(depending on how many partitions there are), so if the end result is
that nothing was pruned, then that's quite a bit of extra effort for no gain.

What we maybe could do better is reduce the cost of the Append scan
when there's a run-time pruning object attached. This is a little
tricky as we currently only build that object when creating the final
plan.=C2=A0 To include that in the costs we'd need to move that to the = Path
generation phase so that we didn't accidentally reject Paths which
could be cheaper than we first think.

> Also, how could I contribute to get this partition pruning to work?
The pgsql-hackers mailing list is where all the discussions about that
happen. There is plenty of past discussions on these topics. One such
(fairly) recent discussion is in [1]. There are plenty more, including
some ideas from Robert Haas about how we might cost run-time partition
pruning. That was likely around 2017-2018 range, so you might need to
dig deep to find that.

David

[1] https://www.postgresq= l.org/message-id/flat/CAApHDvoC7n_oceb%3D8z%2BMY8sTgH4xa%2ByAwBxZ4Dxv8pwkT9= bOcA%40mail.gmail.com#45314d3d01ef8ad1eebe72111989062c


--
Lauro Ojeda
=
--00000000000099cb5b063ff0e804--