Re: Slow GRANT ROLE on PostgreSQL 16 with thousands of ROLEs
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: alex work <alexwork033@gmail.com>
Cc: pgsql-hackers@lists.postgresql.org, Robert Haas <robertmhaas@gmail.com>
Date: 2024-03-21T16:07:36Z
Lists: pgsql-hackers, pgsql-general
Attachments
- grant_with_many_roles.sh (text/x-shellscript)
[ redirecting to -hackers ] alex work <alexwork033@gmail.com> writes: > We encounter slow `GRANT ROLES` only on PostgreSQL 16 instances up to 42 seconds > in production, the client process at PostgresSQL would use 100% of the CPU. > Which is a surprise compared to other instances running older PostgreSQL > releases. On production we have a *LOT* of ROLEs, which unfortunately a case > that we did not test before switching the new servers into production mode. I poked into this a bit. It seems the problem is that as of v16, we try to search for the "best" role membership path from the current user to the target role, and that's done in a very brute-force way, as a side effect of computing the set of *all* role memberships the current role has. In the given case, we could have skipped all that if we simply tested whether the current role is directly a member of the target: it is, so there can't be any shorter path. But in any case roles_is_member_of has horrid performance when the current role is a member of a lot of roles. It looks like part of the blame might be ascribable to catcache.c, as if you look at the problem microscopically you find that roles_is_member_of is causing catcache to make a ton of AUTHMEMMEMROLE catcache lists, and SearchSysCacheList is just iterating linearly through the cache's list-of-lists, so that search is where the O(N^2) time is actually getting taken. Up to now that code has assumed that any one catcache would not have very many catcache lists. Maybe it's time to make that smarter; but since we've gotten away with this implementation for decades, I can't help feeling that the real issue is with roles_is_member_of's usage pattern. For self-containedness, attached is a directly usable shell script to reproduce the problem. The complaint is that the last GRANT takes multiple seconds (about 5s on my machine), rather than milliseconds. regards, tom lane
Commits
-
Optimize roles_is_member_of() with a Bloom filter.
- d365ae705409 17.0 landed
-
Use a hash table for catcache.c's CatCList objects.
- 473182c9523a 17.0 landed
- 14e991db89b1 16.3 landed