Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd365ae7

Browse files
Optimize roles_is_member_of() with a Bloom filter.
When the list of roles gathered by roles_is_member_of() grows verylarge, a Bloom filter is created to help avoid some linear searchesthrough the list. The threshold for creating the Bloom filter isset arbitrarily high and may require future adjustment.Suggested-by: Tom LaneReviewed-by: Tom LaneDiscussion:https://postgr.es/m/CAGvXd3OSMbJQwOSc-Tq-Ro1CAz%3DvggErdSG7pv2s6vmmTOLJSg%40mail.gmail.com
1 parentfad3b5b commitd365ae7

File tree

1 file changed

+65
-3
lines changed
  • src/backend/utils/adt

1 file changed

+65
-3
lines changed

‎src/backend/utils/adt/acl.c

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include"common/hashfn.h"
3737
#include"foreign/foreign.h"
3838
#include"funcapi.h"
39+
#include"lib/bloomfilter.h"
3940
#include"lib/qunique.h"
4041
#include"miscadmin.h"
4142
#include"utils/acl.h"
@@ -78,6 +79,13 @@ static Oidcached_role[] = {InvalidOid, InvalidOid, InvalidOid};
7879
staticList*cached_roles[]= {NIL,NIL,NIL};
7980
staticuint32cached_db_hash;
8081

82+
/*
83+
* If the list of roles gathered by roles_is_member_of() grows larger than the
84+
* below threshold, a Bloom filter is created to speed up list membership
85+
* checks. This threshold is set arbitrarily high to avoid the overhead of
86+
* creating the Bloom filter until it seems likely to provide a net benefit.
87+
*/
88+
#defineROLES_LIST_BLOOM_THRESHOLD 1024
8189

8290
staticconstchar*getid(constchar*s,char*n,Node*escontext);
8391
staticvoidputid(char*p,constchar*s);
@@ -4918,6 +4926,53 @@ RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
49184926
cached_role[ROLERECURSE_SETROLE]=InvalidOid;
49194927
}
49204928

4929+
/*
4930+
* A helper function for roles_is_member_of() that provides an optimized
4931+
* implementation of list_append_unique_oid() via a Bloom filter. The caller
4932+
* (i.e., roles_is_member_of()) is responsible for freeing bf once it is done
4933+
* using this function.
4934+
*/
4935+
staticinlineList*
4936+
roles_list_append(List*roles_list,bloom_filter**bf,Oidrole)
4937+
{
4938+
unsignedchar*roleptr= (unsignedchar*)&role;
4939+
4940+
/*
4941+
* If there is a previously-created Bloom filter, use it to try to
4942+
* determine whether the role is missing from the list. If it says yes,
4943+
* that's a hard fact and we can go ahead and add the role. If it says
4944+
* no, that's only probabilistic and we'd better search the list. Without
4945+
* a filter, we must always do an ordinary linear search through the
4946+
* existing list.
4947+
*/
4948+
if ((*bf&&bloom_lacks_element(*bf,roleptr,sizeof(Oid)))||
4949+
!list_member_oid(roles_list,role))
4950+
{
4951+
/*
4952+
* If the list is large, we take on the overhead of creating and
4953+
* populating a Bloom filter to speed up future calls to this
4954+
* function.
4955+
*/
4956+
if (*bf==NULL&&
4957+
list_length(roles_list)>ROLES_LIST_BLOOM_THRESHOLD)
4958+
{
4959+
*bf=bloom_create(ROLES_LIST_BLOOM_THRESHOLD*10,work_mem,0);
4960+
foreach_oid(roleid,roles_list)
4961+
bloom_add_element(*bf, (unsignedchar*)&roleid,sizeof(Oid));
4962+
}
4963+
4964+
/*
4965+
* Finally, add the role to the list and the Bloom filter, if it
4966+
* exists.
4967+
*/
4968+
roles_list=lappend_oid(roles_list,role);
4969+
if (*bf)
4970+
bloom_add_element(*bf,roleptr,sizeof(Oid));
4971+
}
4972+
4973+
returnroles_list;
4974+
}
4975+
49214976
/*
49224977
* Get a list of roles that the specified roleid is a member of
49234978
*
@@ -4946,6 +5001,7 @@ roles_is_member_of(Oid roleid, enum RoleRecurseType type,
49465001
ListCell*l;
49475002
List*new_cached_roles;
49485003
MemoryContextoldctx;
5004+
bloom_filter*bf=NULL;
49495005

49505006
Assert(OidIsValid(admin_of)==PointerIsValid(admin_role));
49515007
if (admin_role!=NULL)
@@ -5023,16 +5079,22 @@ roles_is_member_of(Oid roleid, enum RoleRecurseType type,
50235079
* graph, we must test for having already seen this role. It is
50245080
* legal for instance to have both A->B and A->C->B.
50255081
*/
5026-
roles_list=list_append_unique_oid(roles_list,otherid);
5082+
roles_list=roles_list_append(roles_list,&bf,otherid);
50275083
}
50285084
ReleaseSysCacheList(memlist);
50295085

50305086
/* implement pg_database_owner implicit membership */
50315087
if (memberid==dba&&OidIsValid(dba))
5032-
roles_list=list_append_unique_oid(roles_list,
5033-
ROLE_PG_DATABASE_OWNER);
5088+
roles_list=roles_list_append(roles_list,&bf,
5089+
ROLE_PG_DATABASE_OWNER);
50345090
}
50355091

5092+
/*
5093+
* Free the Bloom filter created by roles_list_append(), if there is one.
5094+
*/
5095+
if (bf)
5096+
bloom_free(bf);
5097+
50365098
/*
50375099
* Copy the completed list into TopMemoryContext so it will persist.
50385100
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp