submit code to openGauss-server

Offering: openGaussDev

More detail:range分区表PBE单分区剪枝

Signed-off-by:lihaixiao lihaixiao3@huawei.com

Match-id-a88ff128079ca680f33a7419eeab078bacf466d6
This commit is contained in:
openGaussDev
2022-02-26 19:59:59 +08:00
committed by yanghao
parent 75c95e8adf
commit c426a575e3
10 changed files with 228 additions and 3 deletions

View File

@ -678,6 +678,9 @@ static void _outPruningResult(StringInfo str, PruningResult* node)
if (t_thrd.proc->workingVersionNum >= num) {
WRITE_NODE_FIELD(expr);
}
if (t_thrd.proc->workingVersionNum >= PBESINGLEPARTITION_VERSION_NUM) {
WRITE_BOOL_FIELD(isPbeSinlePartition);
}
}
static void _outSubPartitionPruningResult(StringInfo str, SubPartitionPruningResult* node)

View File

@ -3312,6 +3312,9 @@ static PruningResult* _readPruningResult(PruningResult* local_node)
if (t_thrd.proc->workingVersionNum >= num) {
READ_NODE_FIELD(expr);
}
IF_EXIST(isPbeSinlePartition) {
READ_BOOL_FIELD(isPbeSinlePartition);
}
READ_DONE();
}

View File

@ -65,6 +65,7 @@ const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522;
const uint32 UPSERT_WHERE_VERSION_NUM = 92514;
const uint32 FUNC_PARAM_COL_VERSION_NUM = 92500;
const uint32 SUBPARTITION_VERSION_NUM = 92436;
const uint32 PBESINGLEPARTITION_VERSION_NUM = 92523;
const uint32 DEFAULT_MAT_CTE_NUM = 92429;
const uint32 MATERIALIZED_CTE_NUM = 92424;
const uint32 HINT_ENHANCEMENT_VERSION_NUM = 92359;

View File

@ -873,6 +873,31 @@ static void SetPlainReSizeWithPruningRatio(RelOptInfo *rel, double pruningRatio)
}
}
/*
* This function applies only to single partition key of range partitioned tables in PBE mode.
*/
static bool IsPbeSinglePartition(Relation rel, RelOptInfo* relInfo)
{
if (relInfo->pruning_result->paramArg == NULL) {
return false;
}
if (RelationIsSubPartitioned(rel)) {
return false;
}
if (rel->partMap->type != PART_TYPE_RANGE) {
return false;
}
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
int partKeyNum = partMap->partitionKey->dim1;
if (partKeyNum > 1) {
return false;
}
if (relInfo->pruning_result->isPbeSinlePartition) {
return true;
}
return false;
}
/*
* set_plain_rel_size
* Set size estimates for a plain relation (no subquery, no inheritance)
@ -896,8 +921,7 @@ static void set_plain_rel_size(PlannerInfo* root, RelOptInfo* rel, RangeTblEntry
Assert(rel->pruning_result);
if (rel->pruning_result->expr != NULL) {
if (IsPbeSinglePartition(relation, rel)) {
rel->partItrs = 1;
} else {
/* set flag for dealing with partintioned table */

View File

@ -460,17 +460,21 @@ PruningResult* partitionPruningForExpr(PlannerInfo* root, RangeTblEntry* rte, Re
context->pruningType = PruningPartition;
if (rel->partMap != NULL && (rel->partMap->type == PART_TYPE_LIST || rel->partMap->type == PART_TYPE_HASH)) {
// for List/Hash partitioned table
result = partitionEqualPruningWalker(rel->partMap->type, expr, context);
} else {
// for Range/Interval partitioned table
result = partitionPruningWalker(expr, context);
}
if (result->exprPart != NULL || result->paramArg != NULL) {
Param* paramArg = (Param *)copyObject(result->paramArg);
bool isPbeSinlePartition = result->isPbeSinlePartition;
destroyPruningResult(result);
result = getFullPruningResult(rel);
result->expr = expr;
result->paramArg = paramArg;
result->isPbeSinlePartition = isPbeSinlePartition;
return result;
}
/* Never happen, just to be self-contained */
@ -535,10 +539,12 @@ PruningResult* partitionPruningWalker(Expr* expr, PruningContext* pruningCtx)
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
}
result->isPbeSinlePartition = false;
} break;
default: {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
} break;
}
@ -619,6 +625,7 @@ static PruningResult* partitionPruningFromBoolExpr(const BoolExpr* expr, Pruning
if (expr->boolop == NOT_EXPR) {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -638,6 +645,7 @@ static PruningResult* partitionPruningFromBoolExpr(const BoolExpr* expr, Pruning
break;
case OR_EXPR:
result = unionChildPruningResult(resultList, context);
result->isPbeSinlePartition = false;
break;
case NOT_EXPR:
default:
@ -750,6 +758,7 @@ static PruningResult* partitionPruningFromNullTest(NullTest* expr, PruningContex
}
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = true;
result->bm_rangeSelectedPartitions = bms_make_singleton(partMap->rangeElementsNum - 1);
@ -832,6 +841,7 @@ static PruningResult* intersectChildPruningResult(const List* resultList, Prunin
AssertEreport(iteratorResult, MOD_OPT, "iteratorResult context is NNULL.");
if (iteratorResult->state == PRUNING_RESULT_EMPTY) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
return result;
} else if (iteratorResult->state == PRUNING_RESULT_FULL) {
continue;
@ -875,17 +885,22 @@ static PruningResult* intersectChildPruningResult(const List* resultList, Prunin
if (BoundaryIsEmpty(result->boundary)) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
break;
}
result->state = PRUNING_RESULT_SUBSET;
}
if (result->state != PRUNING_RESULT_EMPTY && iteratorResult->isPbeSinlePartition) {
result->isPbeSinlePartition = true;
}
}
if (PruningResultIsEmpty(result)) {
destroyPruningResult(result);
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
result->intervalOffset = -1;
}
@ -981,6 +996,7 @@ static PruningResult* partitionPruningFromScalarArrayOpExpr
if (T_Var != nodeTag(larg) || (T_ArrayExpr != nodeTag(rarg) && T_Const != nodeTag(rarg))) {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1079,6 +1095,7 @@ static PruningResult* partitionPruningFromScalarArrayOpExpr
} else {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
}
@ -1258,6 +1275,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
/* length of args MUST be 2 */
if (!PointerIsValid(expr) || list_length(expr->args) != 2 || !PointerIsValid(opName = get_opname(expr->opno))) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1296,6 +1314,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
((T_Const == nodeTag(rightArg) || T_Param == nodeTag(rightArg)
|| T_OpExpr == nodeTag(rightArg)) && T_Var == nodeTag(leftArg)))) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1325,6 +1344,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
if (context->rte != NULL &&
context->rte->relid != context->relation->rd_id) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
} else {
@ -1334,6 +1354,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
paramArg != NULL ||
exprPart != NULL) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
}
@ -1351,25 +1372,32 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
if (exprPart != NULL) {
if (!PartitionMapIsRange(partMap)) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
} else {
result->exprPart = exprPart;
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = false;
return result;
}
} else if (paramArg != NULL) {
if (paramArg->paramkind != PARAM_EXTERN || !PartitionMapIsRange(partMap)) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
} else {
result->paramArg = paramArg;
result->state = PRUNING_RESULT_SUBSET;
if (0 == strcmp("=", opName)) {
result->isPbeSinlePartition = true;
}
return result;
}
}
if (constArg->constisnull) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
return result;
}
@ -1377,6 +1405,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
result->boundary = makePruningBoundary(partKeyNum);
boundary = result->boundary;
result->isPbeSinlePartition = false;
/* decide the const is the top or bottom of boundary */
if ((0 == strcmp(">", opName) && rightArgIsConst) || (0 == strcmp("<", opName) && !rightArgIsConst)) {
@ -1409,6 +1438,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
boundary->state = PRUNING_RESULT_SUBSET;
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = true;
} else if ((0 == strcmp("<=", opName) && rightArgIsConst) || (0 == strcmp(">=", opName) && !rightArgIsConst)) {
boundary->maxClose[attrOffset] = true;
boundary->max[attrOffset] = PointerGetDatum(constArg);

View File

@ -768,7 +768,11 @@ static void ExecInitPartitionForTidScan(TidScanState* tidstate, EState* estate)
lock = (relistarget ? RowExclusiveLock : AccessShareLock);
tidstate->ss.lockMode = lock;
Assert(plan->scan.itrs == plan->scan.pruningInfo->ls_rangeSelectedPartitions->length);
if (plan->scan.pruningInfo->ls_rangeSelectedPartitions != NULL) {
plan->scan.itrs = plan->scan.pruningInfo->ls_rangeSelectedPartitions->length;
} else {
plan->scan.itrs = 0;
}
foreach (cell, part_seqs) {
Oid table_partitionid = InvalidOid;

View File

@ -44,6 +44,7 @@ extern const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM;
extern const uint32 UPSERT_WHERE_VERSION_NUM;
extern const uint32 FUNC_PARAM_COL_VERSION_NUM;
extern const uint32 SUBPARTITION_VERSION_NUM;
extern const uint32 PBESINGLEPARTITION_VERSION_NUM;
extern const uint32 COMMENT_PROC_VERSION_NUM;
extern const uint32 COMMENT_ROWTYPE_TABLEOF_VERSION_NUM;
extern const uint32 COMMENT_PCT_TYPE_VERSION_NUM;

View File

@ -470,6 +470,8 @@ typedef struct PruningResult {
Param* paramArg;
OpExpr* exprPart;
Expr* expr;
/* This variable applies only to single-partition key range partition tables in PBE mode. */
bool isPbeSinlePartition = false;
} PruningResult;
extern Oid partIDGetPartOid(Relation relation, PartitionIdentifier* partID);

View File

@ -2641,5 +2641,95 @@ delete from test_bypass_sql_partition where col1 <= 11 and col1 >= 15;
delete from test_bypass_sql_partition where col1 > 10;
delete from test_bypass_sql_partition where col1 < 10;
delete from test_bypass_sql_partition where col1 >= 10 and col1 <= 30;
create table t1(
crcrd_acg_setl_dt char(8) not null,
cst_id char(18),
multi_tenancy_id char(5)
)
partition by range (multi_tenancy_id, crcrd_acg_setl_dt)
(
partition p1 values less than ('CN000', '20191201'),
partition p2 values less than ('CN000', '20200201'),
partition p3 values less than ('CN000', '20200202'),
partition p4 values less than ('CN000', '20200203'),
partition p5 values less than ('CN000', '20200204'),
partition p6 values less than ('ZZZZZ', '21000101')
)
enable row movement
;
create index on t1(crcrd_acg_setl_dt, cst_id, multi_tenancy_id) local;
insert into t1 values('20200201', '107190000103394943', 'CN000');
insert into t1 values('20200225', '107190000103394943', 'CN000');
insert into t1 values('20200228', '107190000103394943', 'CN000');
insert into t1 values('20200301', '107190000103394943', 'CN000');
insert into t1 values('20200310', '107190000103394943', 'CN000');
set enable_seqscan = off;
select max(crcrd_acg_setl_dt) from t1 where cst_id='107190000103394943' and multi_tenancy_id = 'CN000';
max
----------
20200310
(1 row)
prepare p1 as select max(crcrd_acg_setl_dt) from t1 where cst_id=$1 and multi_tenancy_id = $2;
execute p1 ('107190000103394943','CN000');
max
----------
20200310
(1 row)
deallocate p1;
drop table t1;
drop table test_range_pt;
ERROR: table "test_range_pt" does not exist
create table test_range_pt (a int, b int, c int)
partition by range(a)
(
partition p1 values less than (2000),
partition p2 values less than (3000),
partition p3 values less than (4000),
partition p4 values less than (5000),
partition p5 values less than (maxvalue)
)ENABLE ROW MOVEMENT;
insert into test_range_pt values(1,1),(2001,2),(3001,3),(4001,4),(5001,5);
create index idx1 on test_range_pt(a) local;
prepare p1 as select max(a) from test_range_pt where a>$1;
execute p1 (1);
max
------
5001
(1 row)
deallocate p1;
select max(a) from test_range_pt where a>b+1;
max
------
5001
(1 row)
drop table test_range_pt;
drop table test_list_lt1;
ERROR: table "test_list_lt1" does not exist
create table test_list_lt1 (a int, b int )
partition by list(a)
(
partition p1 values (2000),
partition p2 values (3000),
partition p3 values (4000)
) ;
prepare p1 as select * from test_list_lt1 where a = $1 and ctid = '(0,1)';
execute p1 (1);
a | b
---+---
(0 rows)
deallocate p1;
drop table test_list_lt1;
reset enable_partition_opfusion;
drop table test_bypass_sql_partition;

View File

@ -250,6 +250,73 @@ delete from test_bypass_sql_partition where col1 <= 11 and col1 >= 15;
delete from test_bypass_sql_partition where col1 > 10;
delete from test_bypass_sql_partition where col1 < 10;
delete from test_bypass_sql_partition where col1 >= 10 and col1 <= 30;
create table t1(
crcrd_acg_setl_dt char(8) not null,
cst_id char(18),
multi_tenancy_id char(5)
)
partition by range (multi_tenancy_id, crcrd_acg_setl_dt)
(
partition p1 values less than ('CN000', '20191201'),
partition p2 values less than ('CN000', '20200201'),
partition p3 values less than ('CN000', '20200202'),
partition p4 values less than ('CN000', '20200203'),
partition p5 values less than ('CN000', '20200204'),
partition p6 values less than ('ZZZZZ', '21000101')
)
enable row movement
;
create index on t1(crcrd_acg_setl_dt, cst_id, multi_tenancy_id) local;
insert into t1 values('20200201', '107190000103394943', 'CN000');
insert into t1 values('20200225', '107190000103394943', 'CN000');
insert into t1 values('20200228', '107190000103394943', 'CN000');
insert into t1 values('20200301', '107190000103394943', 'CN000');
insert into t1 values('20200310', '107190000103394943', 'CN000');
set enable_seqscan = off;
select max(crcrd_acg_setl_dt) from t1 where cst_id='107190000103394943' and multi_tenancy_id = 'CN000';
prepare p1 as select max(crcrd_acg_setl_dt) from t1 where cst_id=$1 and multi_tenancy_id = $2;
execute p1 ('107190000103394943','CN000');
deallocate p1;
drop table t1;
drop table test_range_pt;
create table test_range_pt (a int, b int, c int)
partition by range(a)
(
partition p1 values less than (2000),
partition p2 values less than (3000),
partition p3 values less than (4000),
partition p4 values less than (5000),
partition p5 values less than (maxvalue)
)ENABLE ROW MOVEMENT;
insert into test_range_pt values(1,1),(2001,2),(3001,3),(4001,4),(5001,5);
create index idx1 on test_range_pt(a) local;
prepare p1 as select max(a) from test_range_pt where a>$1;
execute p1 (1);
deallocate p1;
select max(a) from test_range_pt where a>b+1;
drop table test_range_pt;
drop table test_list_lt1;
create table test_list_lt1 (a int, b int )
partition by list(a)
(
partition p1 values (2000),
partition p2 values (3000),
partition p3 values (4000)
) ;
prepare p1 as select * from test_list_lt1 where a = $1 and ctid = '(0,1)';
execute p1 (1);
deallocate p1;
drop table test_list_lt1;
reset enable_partition_opfusion;
drop table test_bypass_sql_partition;