mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 21:11:22 +02:00
Improve performance of find_all_inheritors()
Previous coding uses three nested loops which obviously were a pain for large number of table's children. Patch replaces inner loop with a hashmap. Author: Aleksander Alekseev Reviewed-by: me https://commitfest.postgresql.org/13/1058/
This commit is contained in:
parent
5196f13b27
commit
827d6f9779
@ -31,7 +31,16 @@
|
|||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/tqual.h"
|
#include "utils/tqual.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Entry of a hash table used in find_all_inheritors. See below.
|
||||||
|
*/
|
||||||
|
typedef struct SeenRelsEntry
|
||||||
|
{
|
||||||
|
Oid rel_id; /* relation oid */
|
||||||
|
ListCell *numparents_cell; /* corresponding list cell */
|
||||||
|
} SeenRelsEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* find_inheritance_children
|
* find_inheritance_children
|
||||||
@ -157,10 +166,33 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
|
|||||||
List *
|
List *
|
||||||
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
|
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
|
||||||
{
|
{
|
||||||
|
/* hash table for O(1) rel_oid -> rel_numparents cell lookup */
|
||||||
|
HTAB *seen_rels;
|
||||||
|
HASHCTL ctl;
|
||||||
|
MemoryContext new_ctx;
|
||||||
List *rels_list,
|
List *rels_list,
|
||||||
*rel_numparents;
|
*rel_numparents;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need a separate memory context for a hash table. This is because
|
||||||
|
* hash table is used only in this procedure. To free a memory we need to
|
||||||
|
* call hash_destroy which is just a wrapper around MemoryContextDelete.
|
||||||
|
*/
|
||||||
|
new_ctx = AllocSetContextCreate(CurrentMemoryContext,
|
||||||
|
"FindAllInheritorsSeenRelsContext",
|
||||||
|
ALLOCSET_DEFAULT_SIZES);
|
||||||
|
|
||||||
|
memset(&ctl, 0, sizeof(ctl));
|
||||||
|
ctl.keysize = sizeof(Oid);
|
||||||
|
ctl.entrysize = sizeof(SeenRelsEntry);
|
||||||
|
ctl.hcxt = new_ctx;
|
||||||
|
|
||||||
|
seen_rels = hash_create(
|
||||||
|
"find_all_inheritors temporary table",
|
||||||
|
32, /* start small and extend */
|
||||||
|
&ctl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We build a list starting with the given rel and adding all direct and
|
* We build a list starting with the given rel and adding all direct and
|
||||||
* indirect children. We can use a single list as both the record of
|
* indirect children. We can use a single list as both the record of
|
||||||
@ -190,26 +222,21 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
|
|||||||
foreach(lc, currentchildren)
|
foreach(lc, currentchildren)
|
||||||
{
|
{
|
||||||
Oid child_oid = lfirst_oid(lc);
|
Oid child_oid = lfirst_oid(lc);
|
||||||
bool found = false;
|
bool found;
|
||||||
ListCell *lo;
|
SeenRelsEntry *hash_entry;
|
||||||
ListCell *li;
|
|
||||||
|
|
||||||
|
hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
/* if the rel is already there, bump number-of-parents counter */
|
/* if the rel is already there, bump number-of-parents counter */
|
||||||
forboth(lo, rels_list, li, rel_numparents)
|
lfirst_int(hash_entry->numparents_cell)++;
|
||||||
{
|
|
||||||
if (lfirst_oid(lo) == child_oid)
|
|
||||||
{
|
|
||||||
lfirst_int(li)++;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
/* if it's not there, add it. expect 1 parent, initially. */
|
/* if it's not there, add it. expect 1 parent, initially. */
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
rels_list = lappend_oid(rels_list, child_oid);
|
rels_list = lappend_oid(rels_list, child_oid);
|
||||||
rel_numparents = lappend_int(rel_numparents, 1);
|
rel_numparents = lappend_int(rel_numparents, 1);
|
||||||
|
hash_entry->numparents_cell = rel_numparents->tail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,6 +245,9 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
|
|||||||
*numparents = rel_numparents;
|
*numparents = rel_numparents;
|
||||||
else
|
else
|
||||||
list_free(rel_numparents);
|
list_free(rel_numparents);
|
||||||
|
|
||||||
|
hash_destroy(seen_rels);
|
||||||
|
|
||||||
return rels_list;
|
return rels_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user