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 1vR3lM-005Fj8-1L for pgsql-hackers@arkaria.postgresql.org; Thu, 04 Dec 2025 07:28:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vR3lL-001Tfa-1c for pgsql-hackers@arkaria.postgresql.org; Thu, 04 Dec 2025 07:28:27 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vR3lK-001TfS-27 for pgsql-hackers@lists.postgresql.org; Thu, 04 Dec 2025 07:28:27 +0000 Received: from fout-a2-smtp.messagingengine.com ([103.168.172.145]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vR3lH-0033oG-2M for pgsql-hackers@lists.postgresql.org; Thu, 04 Dec 2025 07:28:26 +0000 Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfout.phl.internal (Postfix) with ESMTP id C2A59EC04C1; Thu, 4 Dec 2025 02:28:20 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Thu, 04 Dec 2025 02:28:20 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1764833300; x=1764919700; bh=NQaSaQaq7h LgdZnJ6mgQtSx79PS8TdX9aAy5SFaieBw=; b=sxBR1ckhM1Llmm/kDe7fYKGKWQ eBIqcF1pHx2aqWV3eod45yUBZ7McSWj94ksL6YA16N2u3rT0jcSlHxwPSSyg5fsU zhYhTS4olyoJKl00ecrVL+UI09eDA9JV9P/7DwZ4TDBsGmPgMzD+ZpZzh2guugMJ PclnHH3BJkjjwxC3dmNHV8dYlLGO4vuolRuYi4H6/yKQZoTUcsrRHeoL6YQID8iI yYXBRlOAgJo0b/HzleN8au4fAKBzWWmDYg6+2W3HYQAdSDIj28g1iZt07maIMFgg X7JTvxg6CdItYCgDq//IcD2zHp0ylj3s7TFVi/FeTXmv9RAS9blA4N0Dgd7A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1764833300; x=1764919700; bh=NQaSaQaq7hLgdZnJ6mgQtSx79PS8TdX9aAy 5SFaieBw=; b=on7kW2LmGiCEJtu9FjGHUsDnGNp9oXzcWjQoF6wnyz26L1cwiwM ZAGLT7xUur84XqDceOkJhkEq5rothqrCdrTXtma8sSpsc0/qpYWWAJO12YYwPIso 2UHe/J8TdsubQiGSRzbpSHbHWHC1RmoXqflqgOuW/xmg6f5tgRI280HyQWdGo7pZ IfVyS0elnu4Fvt9JXO1F41cp9ZH0pVPvDbWpEJbKOmfu2gwZ4WIbmETv0RNULjKI K0qsGLuFNtvfwbXfDpti317+zWyL1iV2UArAp/7nijdApuQ2J4kIHv0baJdf9+Dl pN5rgWv8yfkvh18GwD3fq0S+8Uz3gk4o4ww== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgdegleejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceurghi lhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnegfrhhluc fvnfffucdlfeehmdenucfjughrpeffhffvvefukfhfgggtuggjsehgtderredttdejnecu hfhrohhmpefoihgthhgrvghlucfrrghquhhivghruceomhhitghhrggvlhesphgrqhhuih gvrhdrgiihiieqnecuggftrfgrthhtvghrnhepgeeiveeijeegleeitdeujeehhfeiffei tdefffdufeffvdekgfeihfetuddvvedvnecuffhomhgrihhnpeifihhkihhpvgguihgrrd horhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhep mhhitghhrggvlhesphgrqhhuihgvrhdrgiihiidpnhgspghrtghpthhtohepjedpmhhoug gvpehsmhhtphhouhhtpdhrtghpthhtohepfigrnhhghihupghruhhnthhimhgvseduieef rdgtohhmpdhrtghpthhtoheptghorhgvhidrhhhuihhnkhgvrhesghhmrghilhdrtghomh dprhgtphhtthhopehlihdrvghvrghnrdgthhgrohesghhmrghilhdrtghomhdprhgtphht thhopehjihgrnhdruhhnihhvvghrshgrlhhithihsehgmhgrihhlrdgtohhmpdhrtghpth htohepthhomhgrshesvhhonhgurhgrrdhmvgdprhgtphhtthhopehpghhsqhhlqdhhrggt khgvrhhssehlihhsthhsrdhpohhsthhgrhgvshhqlhdrohhrghdprhgtphhtthhopehtgh hlsehsshhsrdhpghhhrdhprgdruhhs X-ME-Proxy: Feedback-ID: i0fe9450f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 4 Dec 2025 02:28:17 -0500 (EST) Date: Thu, 4 Dec 2025 16:28:00 +0900 From: Michael Paquier To: WangYu Cc: Corey Huinker , Chao Li , jian he , Tomas Vondra , pgsql-hackers@lists.postgresql.org, tgl@sss.pgh.pa.us Subject: Re: Re: Extended Statistics set/restore/clear functions. Message-ID: References: <7648d5c5.7f4.19ae6d8757c.Coremail.wangyu_runtime@163.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="xnWe9iac2CQd+FHZ" Content-Disposition: inline In-Reply-To: <7648d5c5.7f4.19ae6d8757c.Coremail.wangyu_runtime@163.com> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --xnWe9iac2CQd+FHZ Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Dec 04, 2025 at 08:52:16AM +0800, WangYu wrote: > I was reviewing the recent patch > v19-0003-Include-Extended-Statistics-in-pg_dump.patch and noticed a > couple of small typo issues in the explanatory comments =E2=80=94 nothing > that affects the functionality. Please be careful that the mailing lists of Postgres use bottom-posting for thread discussions. Please see here for details: https://en.wikipedia.org/wiki/Posting_style#Bottom-posting > Here are the two minor fixes I=E2=80=99d suggest: > 1. =E2=80=9Cndistintinct=E2=80=9D should be =E2=80=9Cndistinct=E2=80=9D. > 2. =E2=80=9Cdepdendencies=E2=80=9D should be =E2=80=9Cdependencies=E2=80= =9D. Indeed. These exact typos existed in some of the previous iterations of the patch posted on this thread. I have begun looking at 0001 and 0002 more seriously, and can now share a couple of comments about them.=20 My biggest issue with 0001 is the severe lack of documentation for all the routines that are now in attribute_stats.c which are published so as they can be used for the import functions of extended stats: 1) statatt_get_type(), that retrieves a set of information from a relation and one of its attributes. This is lightly documented in extended_statistics_update() from 0002, with an argument claiming that we do the same as attribute statistics. If one then looks at attribute_stats.c, we have a not-really-helpful "derive information =66rom attribute". The trick is that we have an implied dependency here: statatt_get_type() needs to be called *before* statatt_get_elem_type() for attribute *and* extended stats, statatt_get_elem_type() being fed data from statatt_get_type(). 2) statatt_get_elem_type(), interesting piece of the puzzle that acts as a wrapper for the type cache. An important part here, it seems to me, would be to at least tell that this relies on data retrieved from statatt_get_type(), initially. Once I've noticed this dependency the logic felt a bit cleaner to understand, but we have no docs explaining any of that.. 3) statatt_init_empty_tuple(), that initializes a set of data to be used for updates and/or insertion. My first thought here is about=20 "inherited", which turns around an assumption in attribute_statistics_update(). How should callers assign its value? For attribute_statistics_update() it comes as an input argument. Also why are these values initialized as they are and why should these make sense when applied to pg_statistic. Extended stats set the "inherited" argument to false in import_expressions(). That seems equally important to document, both in a comment in extended_stats.c and at the top of the function. Of course it means that this refers to the fact that the stats include values from stats tables, which do not apply to extended stats. But one would have to guess this fact after knowing that this relates to the catalog pg_statistic.. 4) statatt_set_slot is slightly simpler. Still here, it is really easy to miss that this routine should be fed data retrieved by statatt_get_type(). staop can also be an eq or an lt operator. stakind is one of the STATISTIC_KIND_* values, etc, etc. 5) text_to_stavalues() has a bit more explanation, with some data fed =66rom statatt_get_type() for the atttypmod and atttypid. We have also some fix of input coming from statatt_get_elem_type(), for elemtypid. As far as I can see, there is nothing in these functions that require them to be located in attribute_stats.c anymore. Let's move that to stats_utils.c, common place for all the shared facilities used by these stats modules. Or it could also be a new, separate patch, for the manipulation and extraction of the tuple data related to the pg_statistic tuples. I am not OK with these being in attribute_stats.c, and as far as I can see they have no contents that force these routines to=20 Perhaps you know what these imply because you have written this code originally in ce207d2a7901, but exposing them also means that it is very important to document at least some concepts and assumptions around them so as it is possible to guide somebody that may want to use this code: - What are the input arguments from? - And what are the results? - In which circumstances should these be used? Then about 0002. There are a bunch of assumptions embedded inside import_expressions() that are interdependent with the calls of these attribute routines which are a bit hard to evaluate by themselves, at least it's not clear why some of these operations are done and why they are done the way they are presented in the patch. The code processes an array of expressions and processes them in a sequential fashion, repeating checks based on extended_stats_exprs_element. Each step is going to need more explanation to connect the dots. For example, why the first checks on exprs_nulls are important, with a second step of checks for each STATISTIC_KIND_*. Too much is let to the reader to guess, making the code complicated to maintain as written, at least IMHO. Is there any need to locate these new functions and code in extended_stats.c, actually? A separation into a new file seems like it would be a cleaner result, leaving extended_stats.c to deal with the import of the new data, including the fetch and deletion of any existing data in pg_stat_ext that would be updated or inserted. Perhaps name that extended_stats_funcs.c, as these are about the direct SQL functions, import and deletion. For the tests, it looks like it would be better to have everything in a new file, like a stats_ext_import.sql for the clear and restore bits. A lot of the tests are copy-pastes of surrounding queries. Perhaps it would be better to use a SQL function wrapper or an IN clause with multiple relations? The patch has a lot of bloat with these repeated queries.. Perhaps we should use a split for the elements in the extended stats array instead of jsonb_pretty(). The results get quite long here. As of 0002, there are actually two independent pieces dealt with: the deletion of extended stats with pg_clear_extended_stats(), and the insert/update of extended stats with pg_restore_extended_stats(). I'd suggest to split that into two parts, with the clear being first in rank. The deletion is simpler, and getting that in first simplifies the review of the import part with less input to deal with. -- Michael --xnWe9iac2CQd+FHZ Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAmkxOAAACgkQnvQgOdby QH26wBAAoVZXcYBYxehzvWqllap5yYc8Y6tFsoToBvE4sKy7B5WGQtwhVt9jlp8+ UBbH3rYuGQxLHQFObJZn+94nOOMmjobRq81R4OjKluNCZzLdv2/YMeYRi0Ns4TBf Qt9pAwOQKCVtVRrWsq92xDCZPf5LEzH6xM8+np1elRI0aRgdB4qcGPolXgi3wIhz YZuNtDJvzpaY17h+7UHV5PoRHoOQO+bmBvzxoXqaAsjt3LKhJOaR3Y9iXeqxURFH b3fdNrgZRz5nowovL/HJiYCGVddAY9mI1iD/OH6bkzohaxk6IfpaXS0xWhUW27bZ Dbd12IFw8q5PaZrnREhNWyJefboOuGVXMYv7HI6Q/mDCIL/tOIClbo3ISpgq5WR7 65mWAoDP4e+B3f73ErAmyiLkQN51MFJGCr6s5vX3BpIRldrdc2TyI58LlF+bZWEz 1GbDWg67eHi9qm2YaV1H0JTdNST8cVuE/fCW7Gkmz3o8z3M6GiGULDbBCJ4C9xg0 yAYqAOEf6OUHezO2AHoa+lG7v2pkTsu7de5oSnYFzHVfl9eMKQtYZhm8k0GxLVuY 7Bw/GaL1euzqtjjGSMOj3lVCk95W0Cbd3qFcuJUT6fntZJbZrKsOfYLZztT5FcNa Xad5SuBlddqWrPnb5P/gE+R1HvsdrMUQzUDUel7c9Vr2wrQVab8= =EGDH -----END PGP SIGNATURE----- --xnWe9iac2CQd+FHZ--