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.96) (envelope-from ) id 1vTKJu-00HJvj-1u for pgsql-hackers@arkaria.postgresql.org; Wed, 10 Dec 2025 13:33:30 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vTKJt-00BWYa-0c for pgsql-hackers@arkaria.postgresql.org; Wed, 10 Dec 2025 13:33:29 +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.96) (envelope-from ) id 1vTKJs-00BWXz-2U for pgsql-hackers@lists.postgresql.org; Wed, 10 Dec 2025 13:33:29 +0000 Received: from mail-ej1-x62c.google.com ([2a00:1450:4864:20::62c]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vTKJp-0048dL-1o for pgsql-hackers@lists.postgresql.org; Wed, 10 Dec 2025 13:33:28 +0000 Received: by mail-ej1-x62c.google.com with SMTP id a640c23a62f3a-b735b7326e5so149707366b.0 for ; Wed, 10 Dec 2025 05:33:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1765373604; x=1765978404; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=D6n7pEmH8SWZqwBHM+LfAomu/NKVNo/o2/mpk5SCEPw=; b=PPbvIivOxT1okoYhwMiS5L/VcGX/NYEKXzdtZCdkDNIfMY7WFrkSdOyu4UIGkx+LIu 1uBGvcFnSppIJAbPh1RHzIzpLEhiX9ajvHiPK2rNvZTrgEE46hktm8IgrSjG2exQY6VN gZzuUxzP9jmjwX+6qI1xlxXgf125M6SlPrhFV04+Xi2QffVV0zU4/cOhhiVS/ny99fBE NhXn8VlUlreRgMvE+kk8LNp66+cm9TcpT8l07jssTJ7aD5rL3bMRTPf6rcVRwC4kO0IZ alH30xDkFaohAVUgW0H2S3TOxtuZ1D9V21FBf+SsHfD2e88EgdeYfAe+0mskqfaho3pn S15g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765373604; x=1765978404; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=D6n7pEmH8SWZqwBHM+LfAomu/NKVNo/o2/mpk5SCEPw=; b=V7biLoBHJZmuFvrDGqCtJdnSl+2Oe3l3hV+UaT06RXM+vVbFeRV1mpOhNHUvt7vXkr vgwLZLg6XcagQ+JQuScY3KrjxgLovKwG6S1hFNfPSHhexH+dt7278hiVw/0ZrTyEX8Kx jGQJlKiCJ9FR/BXdE1f2KZaky4doNKed2LyOrl09gJu0DNGYHCjKq3kSCeTcSc34TkWP KLJEJsf314XRIXx86NHy46bK8zrTSZLdHYhuN8NEca0yqQpxZ1S03ceJKmmh6m4wbNBP X204NpnXibtAX1vsf9p9Jxl6fDB+boQB10bO1BLMEYPohSNL55pCk2pQpJBkyG/ZQqtm zQGg== X-Forwarded-Encrypted: i=1; AJvYcCUVnOadHG0J+GqPzyJxJgMhbb8AB0vGTf/m3ZFh7eS4NUfU3eTr3VRyzv7ft5ewl2+rakwEGb3QVso/0b9T@lists.postgresql.org X-Gm-Message-State: AOJu0YxXWo28fyVhjUDFk0KaIkF2P6sxCl2jw+zg1ScdHiCPTBUyIG44 EpozRe9+ehelzp/hGMr3oFPeCzI+VJ5PJwPsUC5HROKX8hyCPrA3yyDdiygdUirP9FTH/TdUPpW 4VPVbXKnzV2/nYydgGLLl+HkEPWVkNBI= X-Gm-Gg: AY/fxX5Ae+7msZukQSuksTAtUF3Ga2qwO6vdSWZlM41cbYQAGZ01RbqWKNbBkqcLSzA LCVmUo3krc55hNMXScgIgDlyTXQK6UI3atYVLaTGXqbwJXYudXOgZF5yukL9f5HHAfpECulad0L KKm2khpCHcYvBh1+21GE31fr6c8vRVXG6AT7aZALtdUk4ViwrJ+4YUfnbYJaSIJ+261X1A0lOt/ XQO9aG/023IrHy4RPw3RAqLko3wpFNQGylWZELo/VYzuItvh992/ZgaqfJdoFDOtbzQMlDsquf4 VtUzf+qJfDVLYM0+4YgpXZFp7xc= X-Google-Smtp-Source: AGHT+IHUY3MOTj68RAAOsJ079vyINZfpk85RWMAePiVXMKizCoVTgJQKe/0W4AbSDPCQuxnoR/jP62gGPIkOv/Bcdxg= X-Received: by 2002:a17:907:1c95:b0:b76:cf68:72a7 with SMTP id a640c23a62f3a-b7a6e50e169mr474970966b.27.1765373603638; Wed, 10 Dec 2025 05:33:23 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Robert Haas Date: Wed, 10 Dec 2025 08:33:11 -0500 X-Gm-Features: AQt7F2pThvXDEPoEmmz3iphCcgllqX-O29NjX82dRym0wXZPThW3DW2l694nD5Q Message-ID: Subject: Re: pg_plan_advice To: Jakub Wartak Cc: Dian Fay , Matheus Alcantara , PostgreSQL Hackers Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, Dec 10, 2025 at 6:43=E2=80=AFAM Jakub Wartak wrote: > Quick-question regarding cross-interactions of the extensions: would > it be possible for auto_explain to have something like > auto_explain.log_custom_options=3D'PLAN_ADVICES' so that it could be > dumping the advice of the queries involved Yes, I had the same idea. I think the tricky part here is that an option can have an argument. Most options will probably have Boolean arguments, but there are existing in-core counterexamples, such as FORMAT. We should try to figure out the GUC in such a way that it can be used either to set a Boolean option by just specifying it, or that it can be used to set an option to a value by writing both. Maybe it's fine if the GUC value is just a comma-separated list of entries, and each entry can either be an option name or an option name followed by a space followed by an option value, i.e. if FORMAT were custom, then you could write auto_explain.log_custom_options=3D'format xml, plan_advice' or auto_explain.log_custom_options=3D'plan_advice true, range_table false' and have sensible things happen. In fact, very possibly the GUC should just accept any options whether in-core or out-of-core and not distinguish, so it would be more like auto_explain.log_options. > BTW, some feedback: the plan advices (plan fixing) seems to work fine > for nested queries inside PLPGSQL, and also I've discovered (?) that > one can do even today with patchset the following: > alter function blah(bigint) set pg_plan_advice.advice =3D > 'NESTED_LOOP_MATERIALIZE(b)'; > which seems to be pretty cool, because it allows more targeted fixes > without even having capability of fixing plans for specific query_id > (as discussed earlier). Yes, this is a big advantage of reusing the GUC machinery for this purpose (but see the thread on "[PATCH] Allow complex data for GUC extra"). > For the generation part, the only remaining thing is how it integrates > with partitions (especially the ones being dynamically created/dropped > over time). Right now one needs to keep the advice(s) in sync after > altering the partitions, but it could be expected that some form of > regexp/partition-templating would be built into pg_plan_advices > instead. Anyway, I think this one should go into documentation just as > known-limitations for now. Right. I don't think trying to address this at this stage makes sense. To maintain my sanity, I want to focus for now only on things that round-trip: that is, we can generate it, and then we can accept that same stuff. If we're using a parallel plan for every partition e.g. they are all sequential scans or all index scans, we could generate SEQ_SCAN(foo/*) or similar and then we could accept that. But figuring that out would take a bunch of additional infrastructure that I don't have the time or energy to create right this minute, and I don't see it as anywhere close to essential for v1. Some other problems here: 1. What happens when a small number of partitions are different? The code puts quite a bit of energy into detecting conflicting advice, and honestly probably should put even more, and you might say, well, if there's just one partition that used an index scan, then I still want the advice to read SEQ_SCAN(foo/*) INDEX_SCAN(foo/foo23 foo23_a_idx) and not signal a conflict, but that's slightly unprincipled. 2. INDEX_SCAN() specifications and similar will tend not to be different for every partition because the index names will be different for every partition. You might want something that says "for each partition of foo, use the index on that partition that is a child of this index on the parent". Long run, there's a lot of things that can be added to this to make it more concise (and more expressive, too). Another similar idea is to have something like NO_GATHER_UNLESS_I_SAID_SO() so that a non-parallel query doesn't have to do NO_GATHER(every single relation including all the partitions). I'm pretty sure this is a valuable idea, but, again, it's not essential for v1. > While scratching my head on how to prove that this is not crashing > I've also checked below ones (TLDR all ok): > 1. PG_TEST_INITDB_EXTRA_OPTS=3D"-c > shared_preload_libraries=3D'pg_plan_advice'" meson test # It was clean > 2. PG_TEST_INITDB_EXTRA_OPTS=3D"-c > shared_preload_libraries=3D'pg_plan_advice'" PGOPTIONS=3D"-c > pg_plan_advice.advice=3DNESTED_LOOP_MATERIALIZE(certainlynotused)" meson > test # This had several failures, but all is OK: it's just some of > them had to additional (expected) text inside regression.diffs: > NESTED_LOOP_MATERIALIZE(certainlynotused) /* not matched */ > 3. PG_TEST_INITDB_EXTRA_OPTS=3D"-c > shared_preload_libraries=3D'pg_plan_advice' -c > pg_plan_advice.shared_collection_limit=3D42" meson test # It was clean > too You can set pg_plan_advice.always_explain_supplied_advice=3Dfalse to clean up some of the noise here. This kind of testing is why I invented that option. I think that in production, we REALLY REALLY want any supplied advice to show up in the EXPLAIN plan even if the user did not specify the PLAN_ADVICE option to EXPLAIN. Otherwise, understanding what is going on with an EXPLAIN plan that a hypothetical customer sends to a hypothetical PostgreSQL expert who has to support said hypothetical customer will be a miserable experience. But for testing purposes, it's nice to be able to shut it off so you don't get random regression diffs. --=20 Robert Haas EDB: http://www.enterprisedb.com