public inbox for [email protected]  
help / color / mirror / Atom feed
hash_search_with_hash_value is high in "perf top" on a replica
10+ messages / 7 participants
[nested] [flat]

* hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-01-31 11:30  Dmitry Koterov <[email protected]>
  0 siblings, 3 replies; 10+ messages in thread

From: Dmitry Koterov @ 2025-01-31 11:30 UTC (permalink / raw)
  To: pgsql-hackers

Hi.

Debugging some replication lag on a replica when the master node
experiences heavy writes.

PG "startup recovering" eats up a lot of CPU (like 65 %user and 30 %sys),
which is a little surprising (what is it doing with all those CPU cycles?
it looked like WAL replay should be more IO bound than CPU bound?).

Running "perf top -p <pid>", it shows this:

Samples: 1M of event 'cycles:P', 4000 Hz, Event count (approx.):
18178814660 lost: 0/0 drop: 0/0
Overhead  Shared Object     Symbol
  16.63%  postgres          [.] hash_search_with_hash_value
   5.38%  postgres          [.] __aarch64_ldset4_sync
   4.42%  postgres          [.] __aarch64_cas4_acq_rel
   3.42%  postgres          [.] XLogReadBufferExtended
   2.35%  libc.so.6         [.] 0x0000000000097f4c
   2.04%  postgres          [.] pg_comp_crc32c_armv8
   1.77%  [kernel]          [k] mutex_lock
   1.63%  postgres          [.] XLogPrefetcherReadRecord
   1.56%  postgres          [.] DecodeXLogRecord
   1.55%  postgres          [.] LWLockAcquire

This is more surprising: hash_search_with_hash_value is a hash table lookup
function, is it expected that it is #1 in the profiler? (Called mostly from
PrefetchSharedBuffer*.)

Configuration:
- PG17
- ZFS, compression is off, empty database (with compression on, most of
"startup recovering" CPU was spent in ZFS guts doing
compression/decompression according to the profiler)
- full_page_writes=off, recovery_prefetch=on (ZFS supports it, I tested
with a small C program), wal_decode_buffer_size=2048kB (it doesn't seem to
affect anything though).
- shared_buffers = 25% of RAM
- testing with a giant COPY command basically

My main question is about hash_search_with_hash_value
<https://github.com/postgres/postgres/blob/59d6c03956193f622c069a4ab985bade27384ac4/src/backend/utils...;
CPU usage. With both recovery_prefetch=on and off, it is the topmost
function in "perf top". I see no IO bottleneck on the machine, it's only
"startup recovering" maxing out one CPU core.

Maybe it's a red herring though, but it looks pretty suspicious.


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-01-31 12:24  Srinath Reddy <[email protected]>
  parent: Dmitry Koterov <[email protected]>
  2 siblings, 0 replies; 10+ messages in thread

From: Srinath Reddy @ 2025-01-31 12:24 UTC (permalink / raw)
  To: Dmitry Koterov <[email protected]>; +Cc: [email protected]

On Fri, Jan 31, 2025 at 5:00 PM Dmitry Koterov <[email protected]>
wrote:

> Hi.
>
> Debugging some replication lag on a replica when the master node
> experiences heavy writes.
>
> PG "startup recovering" eats up a lot of CPU (like 65 %user and 30 %sys),
> which is a little surprising (what is it doing with all those CPU cycles?
> it looked like WAL replay should be more IO bound than CPU bound?).
>
> Running "perf top -p <pid>", it shows this:
>
> Samples: 1M of event 'cycles:P', 4000 Hz, Event count (approx.):
> 18178814660 lost: 0/0 drop: 0/0
> Overhead  Shared Object     Symbol
>   16.63%  postgres          [.] hash_search_with_hash_value
>    5.38%  postgres          [.] __aarch64_ldset4_sync
>    4.42%  postgres          [.] __aarch64_cas4_acq_rel
>    3.42%  postgres          [.] XLogReadBufferExtended
>    2.35%  libc.so.6         [.] 0x0000000000097f4c
>    2.04%  postgres          [.] pg_comp_crc32c_armv8
>    1.77%  [kernel]          [k] mutex_lock
>    1.63%  postgres          [.] XLogPrefetcherReadRecord
>    1.56%  postgres          [.] DecodeXLogRecord
>    1.55%  postgres          [.] LWLockAcquire
>
> This is more surprising: hash_search_with_hash_value is a hash table
> lookup function, is it expected that it is #1 in the profiler? (Called
> mostly from PrefetchSharedBuffer*.)
>
> Configuration:
> - PG17
> - ZFS, compression is off, empty database (with compression on, most of
> "startup recovering" CPU was spent in ZFS guts doing
> compression/decompression according to the profiler)
> - full_page_writes=off, recovery_prefetch=on (ZFS supports it, I tested
> with a small C program), wal_decode_buffer_size=2048kB (it doesn't seem to
> affect anything though).
> - shared_buffers = 25% of RAM
> - testing with a giant COPY command basically
>
> My main question is about hash_search_with_hash_value
> <https://github.com/postgres/postgres/blob/59d6c03956193f622c069a4ab985bade27384ac4/src/backend/utils...;
> CPU usage. With both recovery_prefetch=on and off, it is the topmost
> function in "perf top". I see no IO bottleneck on the machine, it's only
> "startup recovering" maxing out one CPU core.
>
> Maybe it's a red herring though, but it looks pretty suspicious.
>
>
Hi,

i think high CPU usage make sense,as hash_search_with_hash_value is called
every time when ever startup process in replica reads a wal and tries to
redo it ,as it goes through readbuffer_common to check if the page which
the wal effects and wants to redo is in buffer pool or not using
BufferAlloc->BufTableLookup>hash_search_with_hash_value.

Regards,
Srinath Reddy Sadipiralla,
EDB: https://www.enterprisedb.com <http://www.enterprisedb.com/;


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-01-31 14:25  Álvaro Herrera <[email protected]>
  parent: Dmitry Koterov <[email protected]>
  2 siblings, 0 replies; 10+ messages in thread

From: Álvaro Herrera @ 2025-01-31 14:25 UTC (permalink / raw)
  To: Dmitry Koterov <[email protected]>; +Cc: pgsql-hackers

On 2025-Jan-31, Dmitry Koterov wrote:

> PG "startup recovering" eats up a lot of CPU (like 65 %user and 30 %sys),
> which is a little surprising (what is it doing with all those CPU cycles?
> it looked like WAL replay should be more IO bound than CPU bound?).
> 
> Running "perf top -p <pid>", it shows this:
> 
> Samples: 1M of event 'cycles:P', 4000 Hz, Event count (approx.):
> 18178814660 lost: 0/0 drop: 0/0
> Overhead  Shared Object     Symbol
>   16.63%  postgres          [.] hash_search_with_hash_value

Yeah, I noticed that this function was showing high in some profiles a
couple of days ago as well.  Looking now at hashfn.c (hash_bytes_uint32
there is the function involved in the buffer mapping hash table), the
comments state that we're updated to Bob Jenkins code from 2006, but
there's a version in his website that (if I read correctly) is twice as
fast as what we're using now:
http://burtleburtle.net/bob/hash/spooky.html

Apparently this code in our repo is mostly unchanged since commit
1f559b7d3aa4, in 2007.

He mentions that on Intel chips, Google's CityHash is faster; but they
in turn claim that the difference is small on Intel chips and that
Jenkins' hash is better on AMD chips.
https://github.com/google/cityhash

Anyway if you wanted to try your luck at improving things, here's your
chance.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-01-31 14:43  Andres Freund <[email protected]>
  parent: Dmitry Koterov <[email protected]>
  2 siblings, 2 replies; 10+ messages in thread

From: Andres Freund @ 2025-01-31 14:43 UTC (permalink / raw)
  To: Dmitry Koterov <[email protected]>; +Cc: pgsql-hackers

Hi,

On 2025-01-31 03:30:35 -0800, Dmitry Koterov wrote:
> Debugging some replication lag on a replica when the master node
> experiences heavy writes.
> 
> PG "startup recovering" eats up a lot of CPU (like 65 %user and 30 %sys),
> which is a little surprising (what is it doing with all those CPU cycles?
> it looked like WAL replay should be more IO bound than CPU bound?).
> 
> Running "perf top -p <pid>", it shows this:
> 
> Samples: 1M of event 'cycles:P', 4000 Hz, Event count (approx.):
> 18178814660 lost: 0/0 drop: 0/0
> Overhead  Shared Object     Symbol
>   16.63%  postgres          [.] hash_search_with_hash_value

It'd be interesting to see what the paths towards hash_search_with_hash_value
are.

You said it's a COPY workloads, which surprises me a bit, because that should
normally be a bit less sensitive to it. Perhaps you have triggers or such that
prevent use of the multi-insert path?



>    5.38%  postgres          [.] __aarch64_ldset4_sync
>    4.42%  postgres          [.] __aarch64_cas4_acq_rel

These two suggest that it might be worth compiling with an -march CPU that
provides native atomics (everything above armv8.1-a, I think).


> Maybe it's a red herring though, but it looks pretty suspicious.

It's unfortunately not too surprising - our buffer mapping table is a pretty
big bottleneck.  Both because a hash table is just not a good fit for the
buffer mapping table due to the lack of locality and because dynahash is
really poor hash table implementation.



Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-02-01 11:46  Dmitry Koterov <[email protected]>
  parent: Andres Freund <[email protected]>
  1 sibling, 1 reply; 10+ messages in thread

From: Dmitry Koterov @ 2025-02-01 11:46 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: pgsql-hackers

> It'd be interesting to see what the paths towards
hash_search_with_hash_value
are.

One of the popular paths is on the screenshot. They are all more or less
the same when recovery_prefetch=on (and when it's off, the replica behaves
worse, more replication lag).

That COPY command - it's the initial sync stage after CREATE SUBSCRIPTION
basically (with streaming=off, default). Large table (hundreds of
gigabytes).

[image: image.png]

It's also interesting, how gradually the disk writes and IOPS grow on the
replica during that large table COPY (dark blue line on the screenshot
below). And in the end, when "EXPLAIN SELECT 1 FROM mytable" showed ~100%
of the rows (i.e. almost everything is copied), it got stuck or ~5 minutes
with a spike on both reads and writes (the dark blue charts are all about
the replica). I.e. that COPY load, it is not spread uniformly: in the end,
it causes more load (I also saw that on the "startup recovering" process
CPU metrics).

[image: CleanShot 2025-02-01 at [email protected]]


On Fri, Jan 31, 2025 at 6:43 AM Andres Freund <[email protected]> wrote:

> Hi,
>
> On 2025-01-31 03:30:35 -0800, Dmitry Koterov wrote:
> > Debugging some replication lag on a replica when the master node
> > experiences heavy writes.
> >
> > PG "startup recovering" eats up a lot of CPU (like 65 %user and 30 %sys),
> > which is a little surprising (what is it doing with all those CPU cycles?
> > it looked like WAL replay should be more IO bound than CPU bound?).
> >
> > Running "perf top -p <pid>", it shows this:
> >
> > Samples: 1M of event 'cycles:P', 4000 Hz, Event count (approx.):
> > 18178814660 lost: 0/0 drop: 0/0
> > Overhead  Shared Object     Symbol
> >   16.63%  postgres          [.] hash_search_with_hash_value
>
> It'd be interesting to see what the paths towards
> hash_search_with_hash_value
> are.
>
> You said it's a COPY workloads, which surprises me a bit, because that
> should
> normally be a bit less sensitive to it. Perhaps you have triggers or such
> that
> prevent use of the multi-insert path?
>
>
>
> >    5.38%  postgres          [.] __aarch64_ldset4_sync
> >    4.42%  postgres          [.] __aarch64_cas4_acq_rel
>
> These two suggest that it might be worth compiling with an -march CPU that
> provides native atomics (everything above armv8.1-a, I think).
>
>
> > Maybe it's a red herring though, but it looks pretty suspicious.
>
> It's unfortunately not too surprising - our buffer mapping table is a
> pretty
> big bottleneck.  Both because a hash table is just not a good fit for the
> buffer mapping table due to the lack of locality and because dynahash is
> really poor hash table implementation.
>
>
>
> Greetings,
>
> Andres Freund
>


Attachments:

  [image/png] image.png (128.3K, ../../CA+CZih4Enpksib2xC8uD2KafOqX=W8-NvC=9qYQDnLsHnQc+PA@mail.gmail.com/3-image.png)
  download | view image

  [image/png] CleanShot 2025-02-01 at [email protected] (104.0K, ../../CA+CZih4Enpksib2xC8uD2KafOqX=W8-NvC=9qYQDnLsHnQc+PA@mail.gmail.com/4-CleanShot%202025-02-01%20at%[email protected])
  download | view image

^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-02-01 14:43  Ants Aasma <[email protected]>
  parent: Andres Freund <[email protected]>
  1 sibling, 1 reply; 10+ messages in thread

From: Ants Aasma @ 2025-02-01 14:43 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: Dmitry Koterov <[email protected]>; pgsql-hackers

On Fri, Jan 31, 2025, 15:43 Andres Freund <[email protected]> wrote:

> > Maybe it's a red herring though, but it looks pretty suspicious.
>
> It's unfortunately not too surprising - our buffer mapping table is a
> pretty
> big bottleneck.  Both because a hash table is just not a good fit for the
> buffer mapping table due to the lack of locality and because dynahash is
> really poor hash table implementation.
>

I measured similar things when looking at apply throughput recently. For
in-cache workloads buffer lookup and locking was about half of the load.

One other direction is to extract more memory concurrency. Prefetcher could
batch multiple lookups together so CPU OoO execution has a chance to fire
off multiple memory accesses at the same time.

The other direction is to split off WAL decoding, buffer lookup and maybe
even pinning to a separate process from the main redo loop.

--
Ants Aasma

>


^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-02-01 15:50  Andres Freund <[email protected]>
  parent: Dmitry Koterov <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Andres Freund @ 2025-02-01 15:50 UTC (permalink / raw)
  To: Dmitry Koterov <[email protected]>; +Cc: pgsql-hackers

Hi,

On 2025-02-01 03:46:33 -0800, Dmitry Koterov wrote:
> > It'd be interesting to see what the paths towards
> hash_search_with_hash_value
> are.
> 
> One of the popular paths is on the screenshot. They are all more or less
> the same when recovery_prefetch=on (and when it's off, the replica behaves
> worse, more replication lag).

Yea, I was hoping for a profile with recovery_prefetch=off, so we can see what
records are causing most of the "slow" lookups.

Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-02-01 15:55  Andres Freund <[email protected]>
  parent: Ants Aasma <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Andres Freund @ 2025-02-01 15:55 UTC (permalink / raw)
  To: Ants Aasma <[email protected]>; +Cc: Dmitry Koterov <[email protected]>; pgsql-hackers

Hi,

On 2025-02-01 15:43:41 +0100, Ants Aasma wrote:
> On Fri, Jan 31, 2025, 15:43 Andres Freund <[email protected]> wrote:
> 
> > > Maybe it's a red herring though, but it looks pretty suspicious.
> >
> > It's unfortunately not too surprising - our buffer mapping table is a
> > pretty
> > big bottleneck.  Both because a hash table is just not a good fit for the
> > buffer mapping table due to the lack of locality and because dynahash is
> > really poor hash table implementation.
> >
> 
> I measured similar things when looking at apply throughput recently. For
> in-cache workloads buffer lookup and locking was about half of the load.
> 
> One other direction is to extract more memory concurrency. Prefetcher could
> batch multiple lookups together so CPU OoO execution has a chance to fire
> off multiple memory accesses at the same time.

I think at the moment we have a *hilariously* cache-inefficient buffer lookup,
that's the first thing to address. A hash table for buffer mapping lookups imo
is a bad idea, due to loosing all locality in a workload that exhibits a *lot*
of locality. But furthermore, dynahash.c is very far from a cache efficient
hashtable implementation.

The other aspect is that in many workloads we'll look up a small set of
buffers over and over, which a) wastes cycles b) wastes cache space for stuff
that could be elided much more efficiently.

We also do a lot of hash lookups for smgr, because we don't have any
cross-record caching infrastructure for that.


> The other direction is to split off WAL decoding, buffer lookup and maybe
> even pinning to a separate process from the main redo loop.

Maybe, but I think we're rather far away from those things being the most
productive thing to tackle.

Greetings,

Andres Freund






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: hash_search_with_hash_value is high in "perf top" on a replica
@ 2025-02-04 19:03  Matthias van de Meent <[email protected]>
  parent: Andres Freund <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Matthias van de Meent @ 2025-02-04 19:03 UTC (permalink / raw)
  To: Andres Freund <[email protected]>; +Cc: Ants Aasma <[email protected]>; Dmitry Koterov <[email protected]>; pgsql-hackers

On Sat, 1 Feb 2025 at 16:55, Andres Freund <[email protected]> wrote:
>
> Hi,
>
> On 2025-02-01 15:43:41 +0100, Ants Aasma wrote:
> > On Fri, Jan 31, 2025, 15:43 Andres Freund <[email protected]> wrote:
> >
> > > > Maybe it's a red herring though, but it looks pretty suspicious.
> > >
> > > It's unfortunately not too surprising - our buffer mapping table is a
> > > pretty
> > > big bottleneck.  Both because a hash table is just not a good fit for the
> > > buffer mapping table due to the lack of locality and because dynahash is
> > > really poor hash table implementation.
> > >
> >
> > I measured similar things when looking at apply throughput recently. For
> > in-cache workloads buffer lookup and locking was about half of the load.
> >
> > One other direction is to extract more memory concurrency. Prefetcher could
> > batch multiple lookups together so CPU OoO execution has a chance to fire
> > off multiple memory accesses at the same time.
>
> I think at the moment we have a *hilariously* cache-inefficient buffer lookup,
> that's the first thing to address. A hash table for buffer mapping lookups imo
> is a bad idea, due to loosing all locality in a workload that exhibits a *lot*
> of locality. But furthermore, dynahash.c is very far from a cache efficient
> hashtable implementation.

In case you might be interested, I've sent a new patch with a new
approach to reducing the buffer lookup table's memory in [0], which
attempts to create a more cache-efficient hash table implementation.

Kind regards,

Matthias van de Meent
Neon (https://neon.tech)

[0] https://www.postgresql.org/message-id/CAEze2WiRo4Zu71jwxYmqjq6XK814Avf2-kytaL6n%3DBreZR2ZbA%40mail.g...






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* [PATCH 2/5] Refactor index_concurrently_create_copy() for use with REPACK (CONCURRENTLY).
@ 2026-02-16 19:49  Antonin Houska <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Antonin Houska @ 2026-02-16 19:49 UTC (permalink / raw)

This patch moves the code to index_create_copy() and adds a "concurrently"
parameter so it can be used by REPACK (CONCURRENTLY).

With the CONCURRENTLY option, REPACK cannot simply swap the heap file and
rebuild its indexes. Instead, it needs to build a separate set of indexes
(including system catalog entries) *before* the actual swap, to reduce the
time AccessExclusiveLock needs to be held for.
---
 src/backend/catalog/index.c      | 54 +++++++++++++++++++++++---------
 src/backend/commands/indexcmds.c |  6 ++--
 src/backend/nodes/makefuncs.c    |  9 +++---
 src/include/catalog/index.h      |  3 ++
 src/include/nodes/makefuncs.h    |  4 ++-
 5 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5ee6389d39c..f8e6c3d804e 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1288,15 +1288,32 @@ index_create(Relation heapRelation,
 /*
  * index_concurrently_create_copy
  *
- * Create concurrently an index based on the definition of the one provided by
- * caller.  The index is inserted into catalogs and needs to be built later
- * on.  This is called during concurrent reindex processing.
- *
- * "tablespaceOid" is the tablespace to use for this index.
+ * Variant of index_create_copy(), called during concurrent reindex
+ * processing.
  */
 Oid
 index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 							   Oid tablespaceOid, const char *newName)
+{
+	return index_create_copy(heapRelation, oldIndexId, tablespaceOid, newName,
+							 true);
+}
+
+/*
+ * index_create_copy
+ *
+ * Create an index based on the definition of the one provided by caller.  The
+ * index is inserted into catalogs. If 'concurrently' is TRUE, it needs to be
+ * built later on, otherwise it's built immediately.
+ *
+ * "tablespaceOid" is the tablespace to use for this index.
+ *
+ * The actual implementation of index_concurrently_create_copy(), reusable for
+ * other purposes.
+ */
+Oid
+index_create_copy(Relation heapRelation, Oid oldIndexId, Oid tablespaceOid,
+				  const char *newName, bool concurrently)
 {
 	Relation	indexRelation;
 	IndexInfo  *oldInfo,
@@ -1315,6 +1332,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 	List	   *indexColNames = NIL;
 	List	   *indexExprs = NIL;
 	List	   *indexPreds = NIL;
+	int			flags = 0;
 
 	indexRelation = index_open(oldIndexId, RowExclusiveLock);
 
@@ -1325,7 +1343,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 	 * Concurrent build of an index with exclusion constraints is not
 	 * supported.
 	 */
-	if (oldInfo->ii_ExclusionOps != NULL)
+	if (oldInfo->ii_ExclusionOps != NULL && concurrently)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("concurrent index creation for exclusion constraints is not supported")));
@@ -1381,9 +1399,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 	}
 
 	/*
-	 * Build the index information for the new index.  Note that rebuild of
-	 * indexes with exclusion constraints is not supported, hence there is no
-	 * need to fill all the ii_Exclusion* fields.
+	 * Build the index information for the new index.
 	 */
 	newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
 							oldInfo->ii_NumIndexKeyAttrs,
@@ -1392,10 +1408,13 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 							indexPreds,
 							oldInfo->ii_Unique,
 							oldInfo->ii_NullsNotDistinct,
-							false,	/* not ready for inserts */
-							true,
+							!concurrently,	/* isready */
+							concurrently,	/* concurrent */
 							indexRelation->rd_indam->amsummarizing,
-							oldInfo->ii_WithoutOverlaps);
+							oldInfo->ii_WithoutOverlaps,
+							oldInfo->ii_ExclusionOps,
+							oldInfo->ii_ExclusionProcs,
+							oldInfo->ii_ExclusionStrats);
 
 	/*
 	 * Extract the list of column names and the column numbers for the new
@@ -1433,6 +1452,9 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 		stattargets[i].isnull = isnull;
 	}
 
+	if (concurrently)
+		flags = INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT;
+
 	/*
 	 * Now create the new index.
 	 *
@@ -1456,7 +1478,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
 							  indcoloptions->values,
 							  stattargets,
 							  reloptionsDatum,
-							  INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
+							  flags,
 							  0,
 							  true, /* allow table to be a system catalog? */
 							  false,	/* is_internal? */
@@ -2450,7 +2472,8 @@ BuildIndexInfo(Relation index)
 					   indexStruct->indisready,
 					   false,
 					   index->rd_indam->amsummarizing,
-					   indexStruct->indisexclusion && indexStruct->indisunique);
+					   indexStruct->indisexclusion && indexStruct->indisunique,
+					   NULL, NULL, NULL);
 
 	/* fill in attribute numbers */
 	for (i = 0; i < numAtts; i++)
@@ -2510,7 +2533,8 @@ BuildDummyIndexInfo(Relation index)
 					   indexStruct->indisready,
 					   false,
 					   index->rd_indam->amsummarizing,
-					   indexStruct->indisexclusion && indexStruct->indisunique);
+					   indexStruct->indisexclusion && indexStruct->indisunique,
+					   NULL, NULL, NULL);
 
 	/* fill in attribute numbers */
 	for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 635679cc1f2..34209bd1393 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -243,7 +243,8 @@ CheckIndexCompatible(Oid oldId,
 	 */
 	indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
 							  accessMethodId, NIL, NIL, false, false,
-							  false, false, amsummarizing, isWithoutOverlaps);
+							  false, false, amsummarizing, isWithoutOverlaps,
+							  NULL, NULL, NULL);
 	typeIds = palloc_array(Oid, numberOfAttributes);
 	collationIds = palloc_array(Oid, numberOfAttributes);
 	opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -930,7 +931,8 @@ DefineIndex(ParseState *pstate,
 							  !concurrent,
 							  concurrent,
 							  amissummarizing,
-							  stmt->iswithoutoverlaps);
+							  stmt->iswithoutoverlaps,
+							  NULL, NULL, NULL);
 
 	typeIds = palloc_array(Oid, numberOfAttributes);
 	collationIds = palloc_array(Oid, numberOfAttributes);
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 2caec621d73..ca7e21e8349 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
 makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
 			  List *predicates, bool unique, bool nulls_not_distinct,
 			  bool isready, bool concurrent, bool summarizing,
-			  bool withoutoverlaps)
+			  bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+			  uint16 *exclusion_strats)
 {
 	IndexInfo  *n = makeNode(IndexInfo);
 
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
 	n->ii_PredicateState = NULL;
 
 	/* exclusion constraints */
-	n->ii_ExclusionOps = NULL;
-	n->ii_ExclusionProcs = NULL;
-	n->ii_ExclusionStrats = NULL;
+	n->ii_ExclusionOps = exclusion_ops;
+	n->ii_ExclusionProcs = exclusion_procs;
+	n->ii_ExclusionStrats = exclusion_strats;
 
 	/* speculative inserts */
 	n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index b259c4141ed..3426087b445 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -99,6 +99,9 @@ extern Oid	index_concurrently_create_copy(Relation heapRelation,
 										   Oid oldIndexId,
 										   Oid tablespaceOid,
 										   const char *newName);
+extern Oid	index_create_copy(Relation heapRelation, Oid oldIndexId,
+							  Oid tablespaceOid, const char *newName,
+							  bool concurrently);
 
 extern void index_concurrently_build(Oid heapRelationId,
 									 Oid indexRelationId);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 982ec25ae14..dcea148ae1a 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
 								List *expressions, List *predicates,
 								bool unique, bool nulls_not_distinct,
 								bool isready, bool concurrent,
-								bool summarizing, bool withoutoverlaps);
+								bool summarizing, bool withoutoverlaps,
+								Oid *exclusion_ops, Oid *exclusion_procs,
+								uint16 *exclusion_strats);
 
 extern Node *makeStringConst(char *str, int location);
 extern DefElem *makeDefElem(char *name, Node *arg, int location);
-- 
2.47.3


--=-=-=
Content-Type: text/x-diff
Content-Disposition: attachment;
 filename=v34-0003-Move-conversion-of-a-historic-to-MVCC-snapshot-to-a-.patch



^ permalink  raw  reply  [nested|flat] 10+ messages in thread


end of thread, other threads:[~2026-02-16 19:49 UTC | newest]

Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-01-31 11:30 hash_search_with_hash_value is high in "perf top" on a replica Dmitry Koterov <[email protected]>
2025-01-31 12:24 ` Srinath Reddy <[email protected]>
2025-01-31 14:25 ` Álvaro Herrera <[email protected]>
2025-01-31 14:43 ` Andres Freund <[email protected]>
2025-02-01 11:46   ` Dmitry Koterov <[email protected]>
2025-02-01 15:50     ` Andres Freund <[email protected]>
2025-02-01 14:43   ` Ants Aasma <[email protected]>
2025-02-01 15:55     ` Andres Freund <[email protected]>
2025-02-04 19:03       ` Matthias van de Meent <[email protected]>
2026-02-16 19:49 [PATCH 2/5] Refactor index_concurrently_create_copy() for use with REPACK (CONCURRENTLY). Antonin Houska <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox