8000 make finish_delayed_invalidation() more lazy · postgrespro/pg_pathman@f5dc278 · GitHub
[go: up one dir, main page]

Skip to content

Commit f5dc278

Browse files
committed
make finish_delayed_invalidation() more lazy
1 parent e0c04c3 commit f5dc278

File tree

7 files changed

+160
-77
lines changed

7 files changed

+160
-77
lines changed

expected/pathman_calamity.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ SELECT context, entries FROM pathman_cache_stats ORDER BY context; /* OK */
867867
maintenance | 0
868868
partition bounds cache | 0
869869
partition dispatch cache | 1
870-
partition parents cache | 10
870+
partition parents cache | 0
871871
(4 rows)
872872

873873
SELECT drop_partitions('calamity.test_pathman_cache_stats');
@@ -910,9 +910,9 @@ SELECT context, entries FROM pathman_cache_stats ORDER BY context; /* OK */
910910
context | entries
911911
--------------------------+---------
912912
maintenance | 0
913-
partition bounds cache | 10
913+
partition bounds cache | 0
914914
partition dispatch cache | 1
915-
partition parents cache | 10
915+
partition parents cache | 0
916916
(4 rows)
917917

918918
SELECT drop_partitions('calamity.test_pathman_cache_stats');

src/hooks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ pathman_relcache_hook(Datum arg, Oid relid)
746746

747747
/* Which means that 'relid' might be parent */
748748
if (relid != InvalidOid)
749-
delay_invalidation_parent_rel(relid);
749+
delay_invalidation_vague_rel(relid);
750750
#ifdef NOT_USED
751751
elog(DEBUG2, "Invalidation message for relation %u [%u]",
752752
relid, MyProcPid);

src/include/init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ bool read_pathman_params(Oid relid,
225225
Datum *values,
226226
bool *isnull);
227227

228+
Oid *read_parent_oids(int *nelems);
229+
228230

229231
bool validate_range_constraint(const Expr *expr,
230232
const PartRelationInfo *prel,

src/include/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ bool match_expr_to_operand(Node *expr, Node *operand);
3131
*/
3232
Oid get_pathman_schema(void);
3333
List * list_reverse(List *l);
34+
int oid_cmp(const void *p1, const void *p2);
3435

3536
/*
3637
* Useful functions for relations.

src/init.c

Lines changed: 89 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ static bool init_pathman_relation_oids(void);
7070
static void fini_pathman_relation_oids(void);
7171
static void init_local_cache(void);
7272
static void fini_local_cache(void);
73-
static void read_pathman_config(void);
73+
74+
/* Special handlers for read_pathman_config() */
75+
static void add_partrel_to_array(Datum *values, bool *isnull, void *context);
76+
static void startup_invalidate_parent(Datum *values, bool *isnull, void *context);
77+
78+
static void read_pathman_config(void (*per_row_cb)(Datum *values,
79+
bool *isnull,
80+
void *context),
81+
void *context);
7482

7583
static bool validate_range_opexpr(const Expr *expr,
7684
const PartRelationInfo *prel,
@@ -82,8 +90,6 @@ static bool read_opexpr_const(const OpExpr *opexpr,
8290
const PartRelationInfo *prel,
8391
Datum *value);
8492

85-
static int oid_cmp(const void *p1, const void *p2);
86-
8793

8894
/* Validate SQL facade */
8995
static uint32 build_sql_facade_version(char *version_cstr);
@@ -202,8 +208,11 @@ load_config(void)
202208
/* Validate pg_pathman's Pl/PgSQL facade (might be outdated) */
203209
validate_sql_facade_version(get_sql_facade_version());
204210

205-
init_local_cache(); /* create various hash tables (caches) */
206-
read_pathman_config(); /* read PATHMAN_CONFIG table & fill cache */
211+
/* Create various hash tables (caches) */
212+
init_local_cache();
213+
214+
/* Read PATHMAN_CONFIG table & fill cache */
215+
read_pathman_config(startup_invalidate_parent, NULL);
207216

208217
/* Register pathman_relcache_hook(), currently we can't unregister it */
209218
if (relcache_callback_needed)
@@ -781,11 +790,83 @@ read_pathman_params(Oid relid, Datum *values, bool *isnull)
781790
}
782791

783792

793+
typedef struct
794+
{
795+
Oid *array;
796+
int nelems;
797+
int capacity;
798+
} read_parent_oids_cxt;
799+
800+
/*
801+
* Get a sorted array of partitioned tables' Oids.
802+
*/
803+
Oid *
804+
read_parent_oids(int *nelems)
805+
{
806+
read_parent_oids_cxt context = { NULL, 0, 0 };
807+
808+
read_pathman_config(add_partrel_to_array, &context);
809+
810+
/* Perform sorting */
811+
qsort(context.array, context.nelems, sizeof(Oid), oid_cmp);
812+
813+
/* Return values */
814+
*nelems = context.nelems;
815+
return context.array;
816+
}
817+
818+
819+
/* read_pathman_config(): add parent to array of Oids */
820+
static void
821+
add_partrel_to_array(Datum *values, bool *isnull, void *context)
822+
{
823+
Oid relid = DatumGetObjectId(values[Anum_pathman_config_partrel - 1]);
824+
read_parent_oids_cxt *result = (read_parent_oids_cxt *) context;
825+
826+
if (result->array == NULL)
827+
{
828+
result->capacity = PART_RELS_SIZE;
829+
result->array = palloc(result->capacity * sizeof(Oid));
830+
}
831+
832+
if (result->nelems >= result->capacity)
833+
{
834+
result->capacity = result->capacity * 2 + 1;
835+
result->array = repalloc(result->array, result->capacity * sizeof(Oid));
836+
}
837+
838+
/* Append current relid */
839+
result->array[result->nelems++] = relid;
840+
}
841+
842+
/* read_pathman_config(): create dummy cache entry for parent */
843+
static void
844+
startup_invalidate_parent(Datum *values, bool *isnull, void *context)
845+
{
846+
Oid relid = DatumGetObjectId(values[Anum_pathman_config_partrel - 1]);
847+
848+
/* Check that relation 'relid' exists */
849+
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
850+
{
851+
DisablePathman(); /* disable pg_pathman since config is broken */
852+
ereport(ERROR,
853+
(errmsg("table \"%s\" contains nonexistent relation %u",
854+
PATHMAN_CONFIG, relid),
855+
errhint(INIT_ERROR_HINT)));
856+
}
857+
858+
/* get_pathman_relation_info() will refresh this entry */
859+
invalidate_pathman_relation_info(relid, NULL);
860+
}
861+
784862
/*
785863
* Go through the PATHMAN_CONFIG table and create PartRelationInfo entries.
786864
*/
787865
static void
788-
read_pathman_config(void)
866+
read_pathman_config(void (*per_row_cb)(Datum *values,
867+
bool *isnull,
868+
void *context),
869+
void *context)
789870
{
790871
Relation rel;
791872
HeapScanDesc scan;
@@ -811,7 +892,6 @@ read_pathman_config(void)
811892
{
812893
Datum values[Natts_pathman_config];
813894
bool isnull[Natts_pathman_config];
814-
Oid relid; /* partitioned table */
815895

816896
/* Extract Datums from tuple 'htup' */
817897
heap_deform_tuple(htup, RelationGetDescr(rel), values, isnull);
@@ -821,21 +901,8 @@ read_pathman_config(void)
821901
Assert(!isnull[Anum_pathman_config_parttype - 1]);
822902
Assert(!isnull[Anum_pathman_config_expr - 1]);
823903

824-
/* Extract values from Datums */
825-
relid = DatumGetObjectId(values[Anum_pathman_config_partrel - 1]);
826-
827-
/* Check that relation 'relid' exists */
828-
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
829-
{
830-
DisablePathman(); /* disable pg_pathman since config is broken */
831-
ereport(ERROR,
832-
(errmsg("table \"%s\" contains nonexistent relation %u",
833-
PATHMAN_CONFIG, relid),
834-
errhint(INIT_ERROR_HINT)));
835-
}
836-
837-
/* get_pathman_relation_info() will refresh this entry */
838-
invalidate_pathman_relation_info(relid, NULL);
904+
/* Execute per row callback */
905+
per_row_cb(values, isnull, context);
839906
}
840907

841908
/* Clean resources */
@@ -1127,20 +1194,6 @@ validate_hash_constraint(const Expr *expr,
11271194
return false;
11281195
}
11291196

1130-
/* needed for find_inheritance_children_array() function */
1131-
static int
1132-
oid_cmp(const void *p1, const void *p2)
1133-
{
1134-
Oid v1 = *((const Oid *) p1);
1135-
Oid v2 = *((const Oid *) p2);
1136-
1137-
if (v1 < v2)
1138-
return -1;
1139-
if (v1 > v2)
1140-
return 1;
1141-
return 0;
1142-
}
1143-
11441197

11451198
/* Parse cstring and build uint32 representing the version */
11461199
static uint32

src/relation_info.c

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ static bool delayed_shutdown = false; /* pathman was dropped */
8888
list = NIL; \
8989
} while (0)
9090

91+
/* Handy wrappers for Oids */
92+
#define bsearch_oid(key, array, array_size) \
93+
bsearch((const void *) &(key), (array), (array_size), sizeof(Oid), oid_cmp)
9194

92-
static bool try_perform_parent_refresh(Oid parent);
95+
96+
static bool try_invalidate_parent(Oid relid, Oid *parents, int parents_count);
9397
static Oid try_syscache_parent_search(Oid partition, PartParentSearch *status);
9498
static Oid get_parent_of_partition_internal(Oid partition,
9599
PartParentSearch *status,
@@ -857,6 +861,9 @@ finish_delayed_invalidation(void)
857861
/* Check that current state is transactional */
858862
if (IsTransactionState())
859863
{
864+
Oid *parents = NULL;
865+
int parents_count;
866+
bool parents_fetched = false;
860867 10000
ListCell *lc;
861868

862869
/* Handle the probable 'DROP EXTENSION' case */
@@ -896,11 +903,19 @@ finish_delayed_invalidation(void)
896903
if (IsToastNamespace(get_rel_namespace(parent)))
897904
continue;
898905

899-
if (!pathman_config_contains_relation(parent, NULL, NULL, NULL, NULL))
900-
remove_pathman_relation_info(parent);
901-
else
906+
/* Fetch all partitioned tables */
907+
if (!parents_fetched)
908+
{
909+
parents = read_parent_oids(&parents_count);
910+
parents_fetched = true;
911+
}
912+
913+
/* Check if parent still exists */
914+
if (bsearch_oid(parent, parents, parents_count))
902915
/* get_pathman_relation_info() will refresh this entry */
903916
invalidate_pathman_relation_info(parent, NULL);
917+
else
918+
remove_pathman_relation_info(parent);
904919
}
905920

906921
/* Process all other vague cases */
@@ -912,8 +927,15 @@ finish_delayed_invalidation(void)
912927
if (IsToastNamespace(get_rel_namespace(vague_rel)))
913928
continue;
914929

930+
/* Fetch all partitioned tables */
931+
if (!parents_fetched)
932+
{
933+
parents = read_parent_oids(&parents_count);
934+
parents_fetched = true;
935+
}
936+
915937
/* It might be a partitioned table or a partition */
916-
if (!try_perform_parent_refresh(vague_rel))
938+
if (!try_invalidate_parent(vague_rel, parents, parents_count))
917939
{
918940
PartParentSearch search;
919941
Oid parent;
@@ -923,21 +945,17 @@ finish_delayed_invalidation(void)
923945

924946
switch (search)
925947
{
926-
/* It's still parent */
948+
/*
949+
* Two main cases:
950+
* - It's *still* parent (in PATHMAN_CONFIG)
951+
* - It *might have been* parent before (not in PATHMAN_CONFIG)
952+
*/
927953
case PPS_ENTRY_PART_PARENT:
928-
{
929-
/* Skip if we've already refreshed this parent */
930-
if (!list_member_oid(fresh_rels, parent))
931-
try_perform_parent_refresh(parent);
932-
}
933-
break;
934-
935-
/* It *might have been* parent before (not in PATHMAN_CONFIG) */
936954
case PPS_ENTRY_PARENT:
937955
{
938956
/* Skip if we've already refreshed this parent */
939957
if (!list_member_oid(fresh_rels, parent))
940-
try_perform_parent_refresh(parent);
958+
try_invalidate_parent(parent, parents, parents_count);
941959
}
942960
break;
943961

@@ -954,6 +972,9 @@ finish_delayed_invalidation(void)
954972

955973
free_invalidation_list(delayed_invalidation_parent_rels);
956974
free_invalidation_list(delayed_invalidation_vague_rels);
975+
976+
if (parents)
977+
pfree(parents);
957978
}
958979
}
959980

@@ -1113,34 +1134,25 @@ try_syscache_parent_search(Oid partition, PartParentSearch *status)
11131134
}
11141135
}
11151136

1116-
/*
1117-
* Try to refresh cache entry for relation 'parent'.
1118-
*
1119-
* Return true on success.
1120-
*/
1137+
/* Try to invalidate cache entry for relation 'parent' */
11211138
static bool
1122-
try_perform_parent_refresh(Oid parent)
1139+
try_invalidate_parent(Oid relid, Oid *parents, int parents_count)
11231140
{
1124-
ItemPointerData iptr;
1125-
Datum values[Natts_pathman_config];
1126-
bool isnull[Natts_pathman_config];
1127-
1128-
if (pathman_config_contains_relation(parent, values, isnull, NULL, &iptr))
1141+
/* Check if this is a partitioned table */
1142+
if (bsearch_oid(relid, parents, parents_count))
11291143
{
1130-
bool should_update_expr = isnull[Anum_pathman_config_cooked_expr - 1];
1131-
1132-
if (should_update_expr)
1133-
pathman_config_refresh_parsed_expression(parent, values, isnull, &iptr);
1144+
/* get_pathman_relation_info() will refresh this entry */
1145+
invalidate_pathman_relation_info(relid, NULL);
11341146

1135-
/* If anything went wrong, return false (actually, it might emit ERROR) */
1136-
refresh_pathman_relation_info(parent,
1137-
values,
1138-
true); /* allow lazy */
1147+
/* Success */
1148+
return true;
11391149
}
1140-
/* Not a partitioned relation */
1141-
else return false;
11421150

1143-
return true;
1151+
/* Clear remaining cache entry */
1152+
remove_pathman_relation_info(relid);
1153+
1154+
/* Not a partitioned relation */
1155+
return false;
11441156
}
11451157

11461158

src/utils.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,21 @@ list_reverse(List *l)
179179
return result;
180180
}
181181

182+
int
183+
oid_cmp(const void *p1, const void *p2)
184+
{
185+
Oid v1 = *((const Oid *) p1);
186+
Oid v2 = *((const Oid *) p2);
187+
188+
if (v1 < v2)
189+
return -1;
190+
191+
if (v1 > v2)
192+
return 1;
193+
194+
return 0;
195+
}
196+
182197

183198

184199
/*

0 commit comments

Comments
 (0)
0