Re: many backends hang on MultiXactOffsetSLRU

2024-09-11 Thread James Pang
 most of query sessions using jdbc connections, the one who use ODBC
one savepoint/per statement, but it does not run any "select for update;
savepoint;update", since row lock conflict, so not easy to touch same row
with update/delete, no idea how that create multixact?   a MultiXact may
contain an update or delete Xid. ?
   in this server, we see thousands of session hang on
‘MultixactOffsetSLRU" but they are in " bind " stage instead of "execute",
why a backend  in "bind" need to access Multixact?

Thanks,

James

Alvaro Herrera  於 2024年9月10日週二 下午5:00寫道:

> On 2024-Sep-10, James Pang wrote:
>
> > There is no foreign keys, but there is one session who did
> transactions
> > to tables with savepoints, one savepoints/per sql in same transaction.
> But
> > sessions with query "SELECT “ do not use savepoints , just with a lot of
> > sessions running same query and hang on MultiXact suddenly.  even only
> one
> > session doing DML with savepoints , and all other queries sessions can
> see
> > this kind of "MultiXact" waiting ,right?
>
> I think SELECT FOR UPDATE combined with savepoints can create
> multixacts, in absence of foreign keys.
>
> A query that's waiting doesn't need to have *created* the multixact or
> subtrans -- it is sufficient that it's forced to look it up.
>
> If thousands of sessions tried to look up different multixact values
> (spread across more than 8 pages), then thrashing of the cache would
> result, with catastrophic performance.  This can probably be caused by
> some operation that creates one multixact per tuple in a few thousand
> tuples.
>
> Maybe you could ease this by doing VACUUM on the table (perhaps with a
> low multixact freeze age), which might remove some of the multixacts.
>
> --
> Álvaro HerreraBreisgau, Deutschland  —
> https://www.EnterpriseDB.com/
> "Para tener más hay que desear menos"
>


Re: Has gen_random_uuid() gotten much slower in v17?

2024-09-11 Thread Peter Eisentraut

On 10.09.24 15:58, David Mullineux wrote:
I'm getting a bit concerned by the slow performance of generating uidds 
on latest dev code versus older versions. Here I compare the time to 
generate 50k random uuids. Both son the same machine.

I must be missing something.


Are you sure that the 18devel installation isn't compiled with 
assertions enabled?


The underlying code for gen_random_uuid() is virtually unchanged between 
PG14 and current.






Re: Has gen_random_uuid() gotten much slower in v17?

2024-09-11 Thread David Mullineux
Good idea. Thanks.I did check. It's not enabled by default but just in
case I did another build. This time explicitly defining --disable-debug and
--disable-cassert. And I tested. Still slower than old versions.

This feels like a build configuration problem. Just can't put my finger on
it yet.

On Wed, 11 Sept 2024, 10:40 Peter Eisentraut,  wrote:

> On 10.09.24 15:58, David Mullineux wrote:
> > I'm getting a bit concerned by the slow performance of generating uidds
> > on latest dev code versus older versions. Here I compare the time to
> > generate 50k random uuids. Both son the same machine.
> > I must be missing something.
>
> Are you sure that the 18devel installation isn't compiled with
> assertions enabled?
>
> The underlying code for gen_random_uuid() is virtually unchanged between
> PG14 and current.
>
>


Re: Partition pruning with array-contains check and current_setting function

2024-09-11 Thread Marcelo Zabani
I managed to get a plan I was hoping for, but it still doesn't prune
partitions. I created a new operator #|<(integer[], integer) that is
defined in SQL and is basically equivalent to value=ANY(array), and a
non-stable tenants() function defined that returns an array from the
setting, and with that I could use a scalar subquery without running into
type-checking errors. This gives me an InitPlan node:

=> SET my.tenant_id='{1}';EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM tbl
WHERE tenant_id #|< (select tenants());
SET
QUERY PLAN
--
 Finalize Aggregate
   InitPlan 1 (returns $0)
 ->  Result
   ->  Gather
 Workers Planned: 2
 Params Evaluated: $0
 ->  Partial Aggregate
   ->  Parallel Append
 ->  Parallel Seq Scan on tbl2 tbl_2
   Filter: (tenant_id = ANY ($0))
 ->  Parallel Seq Scan on tbl1 tbl_1
   Filter: (tenant_id = ANY ($0))




It still doesn't prune even if I EXPLAIN ANALYZE it. I thought maybe I did
something wrong with the operator definition, so I tried making tenants()
immutable and removing the scalar subquery, and then it does prune:
=> SET my.tenant_id='{1}';EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM tbl
WHERE tenant_id #|< tenants();
SET
  QUERY PLAN
--
 Aggregate
   ->  Seq Scan on tbl1 tbl
 Filter: (tenant_id = ANY ('{1}'::integer[]))



Sadly I can't make tenants() immutable because it's a runtime setting, and
making tenants() STABLE does not lead to partition pruning with or without
the scalar subquery around it.

I'm a bit lost. It seems like postgres is fully capable of pruning
partitions for =ANY checks, and some strange detail is confusing it in this
case. I'm not sure what else to try.

On Wed, Aug 7, 2024 at 6:10 PM Marcelo Zabani  wrote:

> Hello all. I am trying to make postgres 16 prune partition for queries
> with `WHERE tenant_id=ANY(current_setting('my.tenant_id')::integer[])`, but
> I haven't been able to make it work, and naturally it impacts performance
> so I thought this list would be appropriate.
>
> Here's the SQL I tried (but feel free to skip to the end as I'm sure all
> this stuff is obvious to you!):
>
>
>
>
>
>
>
>
> *CREATE TABLE tbl (id SERIAL NOT NULL, tenant_id INT NOT NULL, some_col
> INT, PRIMARY KEY (tenant_id, id)) PARTITION BY HASH (tenant_id);CREATE
> TABLE tbl1 PARTITION OF tbl FOR VALUES WITH (MODULUS 2, REMAINDER 0);CREATE
> TABLE tbl2 PARTITION OF tbl FOR VALUES WITH (MODULUS 2, REMAINDER 1);INSERT
> INTO tbl (tenant_id, some_col) SELECT 1, * FROM
> generate_series(1,1);INSERT INTO tbl (tenant_id, some_col) SELECT 3, *
> FROM generate_series(1,1);*
>
> Partition pruning works as expected for this query (still not an
> array-contains check):
> *EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE tenant_id=1;*
>
> When reading from a setting it also prunes partitions correctly:
>
> *SET my.tenant_id=1;EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE
> tenant_id=current_setting('my.tenant_id')::integer;*
>
> It still does partition pruning if we use a scalar subquery. I can see the
> (never executed) scans in the plan.
> *EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE tenant_id=(SELECT
> current_setting('my.tenant_id')::integer);*
>
> But how about an array-contains check? Still prunes, which is nice.
> *EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE
> tenant_id=ANY('{1}'::integer[]);*
>
> However, it doesn't prune if the array is in a setting:
>
> *SET my.tenant_id='{1}';EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE
> tenant_id=ANY(current_setting('my.tenant_id')::integer[]);*
>
> I actually expected that when in a setting, none of the previous queries
> would've done partition pruning because I thought `current_setting` is not
> a stable function. But some of them did, which surprised me.
>
> So I thought maybe if I put it in a scalar query it will give me an
> InitPlan node, but it looks like method resolution for =ANY won't let me
> try this:
> *EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE tenant_id=ANY((SELECT
> current_setting('my.tenant_id')::integer[]));*
> *ERROR:  operator does not exist: integer = integer[]*
>
> I tried using UNNEST, but that adds a Hash Semi Join to the plan which
> also doesn't do partition pruning.
> *EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl WHERE tenant_id=ANY((SELECT
> UNNEST(current_setting('my.tenant_id')::integer[])));*
>
> My question is if there's a way to do partition pruning based on
> array-contains operator if the array is in a setting. The use-case is to
> make Row Level Security policies do partition pruning "automatically" in a
> setting where users can be in more than one tenant.
> It feels like this would work if there were a non-overloaded operator that
> takes in an array and a single element and tests for array-contains,
>