Re: [PATCH] Optionally record Plan IDs to track plan changes for a query

From: Андрей Казачков <andrey(dot)kazachkov(at)tantorlabs(dot)ru>
To: Sami Imseih <samimseih(at)gmail(dot)com>, Lukas Fittl <lukas(at)fittl(dot)com>, Michael Paquier <michael(at)paquier(dot)xyz>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Marko M <marko(at)pganalyze(dot)com>
Subject: Re: [PATCH] Optionally record Plan IDs to track plan changes for a query
Date: 2025-12-25 14:33:11
Message-ID: 404111766672953@mail.360.yandex.ru
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers



Dear PostgreSQL Hackers,


 


I’ve been testing the proposed v5 plan id work and found out instability of


computing the plan identifier after feeding different query texts that


produces the same physical plan trees but with different plan ids. The main


pattern regards with fields of Plan node structures that depend on positions of


RTEs in a RTE list.


 


For your convenience, I’ve attached minimal reproducible examples that


demonstrate this pattern. Both are based on the v6-0001 patch, which


incorporates v5-0001..v5-0003 changes and fixes jumbling empty arrays.


 


```


create table foo1 (num int);


create table foo2 (num int);


 


insert into foo1 (num)


select *


from generate_series(1, 1000);


 


insert into foo2 (num)


select *


from generate_series(1, 10);


 


analyze foo1;


analyze foo2;


 


set compute_plan_id to true;


```


 


The first example changes join order between two tables:


```


explain (costs off, verbose)


select 1 from foo1 join foo2 on foo1.num = foo2.num;


 


            QUERY PLAN


-------------------------------------


 Hash Join


   Output: 1


   Hash Cond: (foo1.num = foo2.num)


   ->  Seq Scan on public.foo1


         Output: foo1.num


   ->  Hash


         Output: foo2.num


         ->  Seq Scan on public.foo2


               Output: foo2.num


 Plan Identifier: 538643160186222168


 


explain (costs off, verbose)


select 1 from foo2 join foo1 on foo1.num = foo2.num;


 


             QUERY PLAN


--------------------------------------


 Hash Join


   Output: 1


   Hash Cond: (foo1.num = foo2.num)


   ->  Seq Scan on public.foo1


         Output: foo1.num


   ->  Hash


         Output: foo2.num


         ->  Seq Scan on public.foo2


               Output: foo2.num


 Plan Identifier: -953143034841089498


```


Here the reordering of relations in the JOIN operator changes their order in


the RTE list, which in turn changes RTE position-sensitive fields like `varno`


in Vars, and those differences leak into jumbling.


 


The second example assumes transformation of some table expressions to a


new form like CTE-inlining or completely its eliminating. Let's see example:


```


explain (costs off, verbose)


WITH foo_cte as (


  SELECT num FROM foo1)


select * from foo_cte;


 


              QUERY PLAN


--------------------------------------


 Seq Scan on public.foo1


   Output: foo1.num


 Plan Identifier: 3494394630757173099


 


explain (costs off, verbose)


select * from foo1;


 


              QUERY PLAN


--------------------------------------


 Seq Scan on public.foo1


   Output: num


 Plan Identifier: 8116143677260771228


```


In the example with a CTE, RTE list contains the outdated subquery item and the


relation one, whereas without a CTE we have just the relation item. Although


the CTE is inlined, its RTE is not removed from the rtable; as a result,


position-sensitive fields (such as `varno` for Vars) differ from the no-CTE


case.


 


A possible way to address it during jumbling process:


1. Remove/skip unused RTE list elements.


2. Sort active RTE list elements by some stable criteria.


3. Adjust fields referring to active RTEs.


 


But the main challenge is identifying all “position-sensitive” fields across


node types efficiently and maintainably. I’d happy to see your feedback on


this issue.


 


Additionally, I noticed that the `location` field is being jumbled for several


structures (for example, `Var`). Since it’s only a token location, I believe we


should not include it in the final plan id value.


 


--


Sincerely,


Andrey Kazachkov

Attachment Content-Type Size
unknown_filename text/html 4.6 KB
v6-0001-Add-plan_id-support-to-the-core.patch text/x-diff 43.7 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Artem Gavrilov 2025-12-25 15:11:15 Re: Timeline switching with partial WAL records can break replica recovery
Previous Message Андрей Казачков 2025-12-25 14:27:19 Re: [PATCH] Optionally record Plan IDs to track plan changes for a query