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 1wN54n-000YtC-0X for pgsql-hackers@arkaria.postgresql.org; Wed, 13 May 2026 08:36:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wN54j-008Blt-2Q for pgsql-hackers@arkaria.postgresql.org; Wed, 13 May 2026 08:36:17 +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 1wN54j-008Bll-1G for pgsql-hackers@lists.postgresql.org; Wed, 13 May 2026 08:36:17 +0000 Received: from mail-pg1-x534.google.com ([2607:f8b0:4864:20::534]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wN54g-00000000N44-3L9M for pgsql-hackers@postgresql.org; Wed, 13 May 2026 08:36:17 +0000 Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-c798fc1a28cso3021555a12.3 for ; Wed, 13 May 2026 01:36:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778661370; x=1779266170; darn=postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=fTh8BqqeZQlq7avMNF+NzOo0Hy8s5TdTmFlz0FxWbgQ=; b=pVho/IXgFx6+jRpscu97+oXAFe1NJcURvMCAwtZUPUlsIEKbjUhh/jRCNzuOYWCx3T tNNOFWmhEGA0jkKvyWLecp1lybGNpOOCv1QQZ+HAljZpPL5S9kFTBXCZJOCDLIEPkCp1 eOyFZNcNQGleygfkW09wIReWx1S7L6LLO1g0ty0ZpQ8eqp+h7qCLrKRBTawW+JT6C6mx o8B5vnwx+LBRkwaJxnLynJ6VYFJ1q8CxtGrGOgH6kWlIiHRv00wuIpVrTUYo2x4281ME Q6ezjryUeXwS2jNFbPPEg1R75m+096arwtFtVTJsCuOfYGs7ThffFi+WQR5GG27LeFdk OKSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778661370; x=1779266170; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=fTh8BqqeZQlq7avMNF+NzOo0Hy8s5TdTmFlz0FxWbgQ=; b=QpTidCY9yYB2izkEQr6CcqtjwDiy7OOM5tK7aKyU6/rv6/Icw72iHa2Xt+fxuw8dCg NYlPXuNyQijs1UEBU35KwXacfTgs2SPgNXZ7dMREYvBC/3vQ3o/qXUsTw0U3RRHEC/vZ /B55PDd9ob9OXuRUtLtCTu0aSGIG4CSMg1xC0xbehqitjipVyW1Olu28L+aue+Zgmbsd uNuABuD+hc0hhoi+wUX2JPCJTbtOMAZ2qjChDa37hM4JZTE7jTsCwHSi6PCpeiOPqLam zDeiiGRMSxsL4UsRWlIa0XsNZGnxWFN/UJgLWZ+uK+LrRzniqLN1d0dHRbTksioyN2Vv LyHQ== X-Forwarded-Encrypted: i=1; AFNElJ+ekpHDskuzkVssgW6Ga6xK1ThwH1htRTK8qhmmHhgLevwePhxaNa/A0JI3ML22Tfr+5R1q3QoTYytU1PM6@postgresql.org X-Gm-Message-State: AOJu0YywixwuQOujy+mcmvVJa58whzKd8B8NTe3cyfJeAs38Ob1ytmhw WTyCK6NGfTKjczYZFnbYr6oiBElmSbvnsg2ECusbQltJ7077zXg5ZUYI X-Gm-Gg: Acq92OF5IQPWALzYxg/Fm0tyVNGSIrq0H9i8PONwdSHsxfUjuPEqGLxQmSo1/URjvYl CDTDRBoa/eUxiT5rdgEtlKIXon1JdrOZcrEtc3ko3TlkhP/xIta0YAFz2lkXVgkfWxUpGqZBcMy iRFKXAuFggb4/2vMPhfAYKhZaJm84U8KMzaokXUAch+eGWeikcmw7Ds7gaC8lqerzQw+6dqD2p0 xyE8OqsROrxiTskrWVi8JXJffua5u64NcoBoOPpYTkFTDcJsvpNyDoD+oNezWZ/p39WJAMr0d20 gSFsXmRuFOGdGNZGlR4N1ORp51znJRgwv/Fc3/94cMHDCB5rBj0COvzkNKENvofHhxnVwVXxtyX 5x8wVF6iJkRgTK4r0vwEoRS7FrlvDJy5nwLSzQuOIeXhUMkx8LIdI8JnwZxgvn37/twB8FO7LI4 M46NfKnrNIQUnigky7inPAEovZbkAYevQ= X-Received: by 2002:a17:903:22d0:b0:2ba:4eee:6c1e with SMTP id d9443c01a7336-2bd2716a288mr25456015ad.15.1778661370363; Wed, 13 May 2026 01:36:10 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2baf1d3fed8sm163832525ad.27.2026.05.13.01.36.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 May 2026 01:36:09 -0700 (PDT) From: Chao Li Message-Id: <69CA7636-0359-42B6-B971-16A036698187@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_D9742CE3-0BC0-4353-841C-21EF37D07666" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: Fix REPACK with WITHOUT OVERLAPS replica identity indexes Date: Wed, 13 May 2026 16:35:30 +0800 In-Reply-To: <70401.1778604528@localhost> Cc: alvherre@kurilemu.de, Kirill Reshke , PostgreSQL-development To: Antonin Houska References: <70401.1778604528@localhost> X-Mailer: Apple Mail (2.3864.400.21) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_D9742CE3-0BC0-4353-841C-21EF37D07666 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On May 13, 2026, at 00:48, Antonin Houska wrote: >=20 > =C3=81lvaro Herrera wrote: >=20 >> On 2026-May-11, Chao Li wrote: >>=20 >>>> On May 10, 2026, at 06:38, =C3=81lvaro Herrera = wrote: >>=20 >>>> I think it would be a good idea to make identity_key_equal() not = deform >>>> all attributes, but instead only up to the last one it needs for = the key >>>> comparisons. >>>=20 >>> That=E2=80=99s true. Please see v3. >>=20 >> Thanks. I did one further small change, namely to determine these = last >> attnums just once per run rather than once per tuple. Pushed now. >=20 > I appreciate that REPACK can handle more cases now! However, I found a = problem > (or at least a question) when rebasing the improvements for the next > release(s). (It's related to splitting the table scan into multiple = block > ranges and use one snapshot per range, details are not too important = here, ) > Assertion failure in the new code made me think if other than B-tree = indexes > should be allowed in the USING INDEX clause of REPACK. >=20 > AFAICS, only B-tree indexes (and some special ones that don't appear = in the > core) provide ordering information - see get_relation_info(): >=20 > /* > * Fetch the ordering information for the index, if any. > */ > if (info->relam =3D=3D BTREE_AM_OID) > { > ... > info->sortopfamily =3D info->opfamily; > ... > } > else if (amroutine->amcanorder) > { > /* > * Otherwise, identify the corresponding btree opfamilies > * by trying to map this index's "<" operators into btree. > * Since "<" uniquely defines the behavior of a sort > * order, this is a sufficient test. > ... > } > else > { > ... > info->sortopfamily =3D NULL; > ... > } >=20 >=20 > Therefore, index scan shouldn't be possible for GIST index - see > build_index_paths(): >=20 > index_is_ordered =3D (index->sortopfamily !=3D NULL); >=20 >=20 > So I'm not sure if clustering makes sense here. What makes me confused = is that > GIST has IndexAmRoutine.amclusterable=3Dtrue. As it has = amcanorder=3Dfalse at the > same time, I suspect it might be just a thinko. However, if we simply = set > amclusterable to false, it can break upgrade to PG 19 for users who = already > "clustered" some table by a GIST index (for mysterious reasons). (BTW, = do we > need the amclusterable field at all?) >=20 > REPACK currently rejects explicit sort if non-B-tree index is = specified (due > to lack of ordering information), but it still scans the index rather = than > the heap - see copy_table_data() and = heapam_relation_copy_for_cluster(). >=20 > Does this seem worth fixing now? Or maybe at least worth some comments = (unless > I'm completely wrong)? After some investigation, I think I see the mismatch: * get_relation_info(): non-ordered GiST cannot provide sort order. That = is expected. * copy_table_data() only uses plan_cluster_use_sort() for btree. For any = other clusterable index, it sets use_sort =3D false and does a raw index = scan. * The docs say REPACK can re-sort using index scan =E2=80=9Cif the index = is a b-tree=E2=80=9D or seqscan+sort, which does not describe what the = code actually does for GiST. I am not sure whether we should change the behavior in PG19. Alvaro may = have a better idea about that. But I agree that we can at least clarify = the code comment and documentation. The attached patch attempts to do = that. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_D9742CE3-0BC0-4353-841C-21EF37D07666 Content-Disposition: attachment; filename=repack_comment.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="repack_comment.diff" Content-Transfer-Encoding: 7bit diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml index 0cb72b6b289..c9ef358261e 100644 --- a/doc/src/sgml/ref/repack.sgml +++ b/doc/src/sgml/ref/repack.sgml @@ -78,11 +78,13 @@ REPACK [ ( option [, ...] ) ] USING If the USING INDEX clause is specified, the rows in - the table are stored in the order that the index specifies; - clustering, because rows are physically clustered - afterwards. - If an index name is specified in the command, the order implied by that - index is used, and that index is configured as the index to cluster on. + the table are physically rearranged according to the specified index; + this is known as clustering. For b-tree indexes, + this means the table is stored in the index's sort order. Other clusterable + index access methods use their own index scan order, which does not + necessarily correspond to a SQL sort order. + If an index name is specified in the command, that index is used for + clustering, and is configured as the index to cluster on. (This also applies to an index given to the CLUSTER command.) If no index name is specified, then the index that has @@ -101,12 +103,12 @@ REPACK [ ( option [, ...] ) ] USING Clustering is a one-time operation: when the table is subsequently updated, the changes are not clustered. That is, no attempt - is made to store new or updated rows according to their index order. (If - one wishes, one can periodically recluster by issuing the command again. - Also, setting the table's fillfactor storage parameter - to less than 100% can aid in preserving cluster ordering during updates, - since updated rows are kept on the same page if enough space is available - there.) + is made to store new or updated rows according to the clustering order. + (If one wishes, one can periodically recluster by issuing the command + again. Also, setting the table's fillfactor storage + parameter to less than 100% can aid in preserving cluster ordering during + updates, since updated rows are kept on the same page if enough space is + available there.) @@ -123,11 +125,12 @@ REPACK [ ( option [, ...] ) ] USING - REPACK can re-sort the table using either an index scan - on the specified index (if the index is a b-tree), or a sequential scan - followed by sorting. It will attempt to choose the method that will be - faster, based on planner cost parameters and available statistical - information. + When clustering on a b-tree index, REPACK can rewrite + the table using either an index scan on the specified index, or a + sequential scan followed by sorting. It will attempt to choose the method + that will be faster, based on planner cost parameters and available + statistical information. When clustering on a non-b-tree index, + REPACK uses an index scan. diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 860e2aecbe9..6eb685b2240 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -1364,10 +1364,16 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, /* * Decide whether to use an indexscan or seqscan-and-optional-sort to scan - * the OldHeap. We know how to use a sort to duplicate the ordering of a - * btree index, and will use seqscan-and-sort for that case if the planner - * tells us it's cheaper. Otherwise, always indexscan if an index is - * provided, else plain seqscan. + * the OldHeap. For btree indexes, the scan order is a well-defined sort + * order that can also be reproduced by an explicit sort, so use the + * planner to choose between indexscan and seqscan-and-sort. + * + * Other index AMs can be marked clusterable even though they do not + * provide btree-style ordering information to the planner. For those, + * clustering means rewriting the heap in the AM's index scan order, which + * may improve locality but cannot be duplicated by sorting here, so leave + * use_sort false. If no index is provided, use a plain seqscan. + */ if (OldIndex != NULL && OldIndex->rd_rel->relam == BTREE_AM_OID) use_sort = plan_cluster_use_sort(RelationGetRelid(OldHeap), --Apple-Mail=_D9742CE3-0BC0-4353-841C-21EF37D07666--