0001-cache-bound-offset_v2.patch
application/octet-stream
Filename: 0001-cache-bound-offset_v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v2-0001
| File | + | − |
|---|---|---|
| src/backend/executor/execPartition.c | 78 | 21 |
| src/backend/partitioning/partdesc.c | 2 | 0 |
| src/include/partitioning/partdesc.h | 3 | 0 |
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 606c920b06..a775bda553 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1246,12 +1246,14 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull)
int part_index = -1;
PartitionKey key = pd->key;
PartitionDesc partdesc = pd->partdesc;
+ int cached_off = partdesc->cached_bound_offset;
PartitionBoundInfo boundinfo = partdesc->boundinfo;
/* Route as appropriate based on partitioning strategy. */
switch (key->strategy)
{
case PARTITION_STRATEGY_HASH:
+ Assert(cached_off < 0);
{
uint64 rowHash;
@@ -1272,14 +1274,33 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull)
}
else
{
- bool equal = false;
-
- bound_offset = partition_list_bsearch(key->partsupfunc,
- key->partcollation,
- boundinfo,
- values[0], &equal);
- if (bound_offset >= 0 && equal)
- part_index = boundinfo->indexes[bound_offset];
+ if (cached_off >= 0)
+ {
+ Datum bound_datum = boundinfo->datums[cached_off][0];
+ int32 cmpval;
+
+ cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0],
+ key->partcollation[0],
+ bound_datum,
+ values[0]));
+ if (cmpval == 0)
+ part_index = boundinfo->indexes[cached_off];
+ }
+
+ if (part_index < 0)
+ {
+ bool equal = false;
+
+ bound_offset = partition_list_bsearch(key->partsupfunc,
+ key->partcollation,
+ boundinfo,
+ values[0], &equal);
+ if (bound_offset >= 0 && equal)
+ {
+ part_index = boundinfo->indexes[bound_offset];
+ partdesc->cached_bound_offset = bound_offset;
+ }
+ }
}
break;
@@ -1304,20 +1325,56 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull)
if (!range_partkey_has_null)
{
- bound_offset = partition_range_datum_bsearch(key->partsupfunc,
- key->partcollation,
- boundinfo,
- key->partnatts,
- values,
- &equal);
+ if (cached_off >= 0)
+ {
+ Datum *bound_datums = boundinfo->datums[cached_off];
+ PartitionRangeDatumKind *bound_kind = boundinfo->kind[cached_off];
+ int32 cmpval;
+
+ /* Check if the value is above the low bound */
+ cmpval = partition_rbound_datum_cmp(key->partsupfunc,
+ key->partcollation,
+ bound_datums,
+ bound_kind,
+ values,
+ key->partnatts);
+ if (cmpval == 0)
+ part_index = boundinfo->indexes[cached_off + 1];
+ else if (cmpval < 0 && cached_off + 1 < boundinfo->ndatums)
+ {
+ /* Check if the value is below the high bound */
+ bound_datums = boundinfo->datums[cached_off + 1];
+ bound_kind = boundinfo->kind[cached_off + 1];
+ cmpval = partition_rbound_datum_cmp(key->partsupfunc,
+ key->partcollation,
+ bound_datums,
+ bound_kind,
+ values,
+ key->partnatts);
+
+ if (cmpval > 0)
+ part_index = boundinfo->indexes[cached_off + 1];
+ }
+ }
- /*
- * The bound at bound_offset is less than or equal to the
- * tuple value, so the bound at offset+1 is the upper
- * bound of the partition we're looking for, if there
- * actually exists one.
- */
- part_index = boundinfo->indexes[bound_offset + 1];
+ if (part_index < 0)
+ {
+ bound_offset = partition_range_datum_bsearch(key->partsupfunc,
+ key->partcollation,
+ boundinfo,
+ key->partnatts,
+ values,
+ &equal);
+
+ /*
+ * The bound at bound_offset is less than or equal to the
+ * tuple value, so the bound at offset+1 is the upper
+ * bound of the partition we're looking for, if there
+ * actually exists one.
+ */
+ part_index = boundinfo->indexes[bound_offset + 1];
+ partdesc->cached_bound_offset = bound_offset;
+ }
}
}
break;
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index 9a9d6a9643..e6ec01de71 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -285,6 +285,8 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
MemoryContextAllocZero(new_pdcxt, sizeof(PartitionDescData));
partdesc->nparts = nparts;
partdesc->detached_exist = detached_exist;
+ partdesc->cached_bound_offset = -1;
+
/* If there are no partitions, the rest of the partdesc can stay zero */
if (nparts > 0)
{
diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h
index 0792f48507..9df28ae14f 100644
--- a/src/include/partitioning/partdesc.h
+++ b/src/include/partitioning/partdesc.h
@@ -36,6 +36,9 @@ typedef struct PartitionDescData
* the corresponding 'oids' element belongs to
* a leaf partition or not */
PartitionBoundInfo boundinfo; /* collection of partition bounds */
+ int cached_bound_offset; /* offset of the bound datum most
+ * recently chosen by
+ * get_partition_for_tuple() */
} PartitionDescData;