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;