Skip to content

Commit

Permalink
[ORCA] Implemented InPlaceUpdate to be used for updates made on non-d…
Browse files Browse the repository at this point in the history
…istribution columns. (#13889)

Implemented InPlaceUpdate to be used for updates made on non-distribution columns.
Currently, ORCA uses Split-Update for updates on both distribution
and non-distribution columns. With this commit,
ORCA uses an InPlaceUpdate whenever updates are made to
non-distribution columns or non-partition keys, and Split Update
if any of modified columns are either distribution or partition keys.
Consider below setup where we are updating
non-distibution column, b in the table foo.

`
create table foo(a int, b int);
explain update foo set b=4;
`
ORCA produces plan with Split and Update nodes

```
Update on public.foo
   ->  Result
         Output: foo_1.a, foo_1.b, (DMLAction), foo_1.ctid, foo_1.gp_segment_id
         ->  Split
               Output: foo_1.a, foo_1.b, foo_1.ctid, foo_1.gp_segment_id, DMLAction
               ->  Seq Scan on public.foo foo_1
                     Output: foo_1.a, foo_1.b, 4, foo_1.ctid, foo_1.gp_segment_id
```

There is no point in using a Split and Update for this as we are updating a
non-distribution column which do not require any redistribution. This
commit uses an InPlace Update to perform updates on non-distribution
columns like Planner. Below is the new plan produced with this commit.

New Plan
```
Update on public.foo
   ->  Seq Scan on public.foo foo_1
         Output: foo_1.a, 4, foo_1.ctid, foo_1.gp_segment_id
 Optimizer: Pivotal Optimizer (GPORCA)
```
  • Loading branch information
Sanath97 authored and KnightMurloc committed Dec 20, 2023
1 parent e730004 commit a02d221
Show file tree
Hide file tree
Showing 47 changed files with 1,169 additions and 1,282 deletions.
43 changes: 34 additions & 9 deletions src/backend/executor/nodeDML.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,21 @@ ExecDML(DMLState *node)
{
return NULL;
}
EvalPlanQualSetSlot(&node->mt_epqstate, slot);


bool isnull = false;
int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);
DMLAction action = -1;
bool isUpdate = node->ps.state->es_plannedstmt->commandType == CMD_UPDATE;

bool isUpdate = false;
if (node->ps.state->es_plannedstmt->commandType == CMD_UPDATE)
// if it's not in place update
if(plannode->actionColIdx)
{
isUpdate = true;
action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);
Assert(action == DML_INSERT || action == DML_DELETE);
}

Assert(action == DML_INSERT || action == DML_DELETE);


/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle.
Expand Down Expand Up @@ -155,7 +156,7 @@ ExecDML(DMLState *node)
isUpdate,
InvalidOid);
}
else /* DML_DELETE */
else if (action == DML_DELETE)
{
int32 segid = GpIdentity.segindex;
Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull);
Expand Down Expand Up @@ -183,6 +184,26 @@ ExecDML(DMLState *node)
PLANGEN_OPTIMIZER /* Plan origin */,
isUpdate);
}
else /* DML_UPDATE */
{
int32 segid = GpIdentity.segindex;

Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull);

ItemPointer tupleid = (ItemPointer) DatumGetPointer(ctid);
ItemPointerData tuple_ctid = *tupleid;
tupleid = &tuple_ctid;

ExecUpdate(
tupleid,
segid,
NULL, //oldtuple
node->cleanedUpSlot,
NULL, //planSlot
&node->mt_epqstate,
node->ps.state,
true);
}

return slot;
}
Expand Down Expand Up @@ -218,6 +239,8 @@ ExecInitDML(DML *node, EState *estate, int eflags)
Plan *outerPlan = outerPlan(node);
outerPlanState(dmlstate) = ExecInitNode(outerPlan, estate, eflags);

EvalPlanQualInit(&dmlstate->mt_epqstate, estate, outerPlan, NIL, 0);

/*
* ORCA Plan does not seem to set junk attribute for "gp_segment_id", else we
* could call the simple code below.
Expand Down Expand Up @@ -261,6 +284,7 @@ ExecInitDML(DML *node, EState *estate, int eflags)
dmlstate->junkfilter = ExecInitJunkFilter(node->plan.targetlist,
dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att->tdhasoid,
dmlstate->cleanedUpSlot);
estate->es_result_relation_info->ri_junkFilter = dmlstate->junkfilter;

/*
* We don't maintain typmod in the targetlist, so we should fixup the
Expand Down Expand Up @@ -311,6 +335,7 @@ ExecEndDML(DMLState *node)
ExecFreeExprContext(&node->ps);
ExecClearTuple(node->ps.ps_ResultTupleSlot);
ExecClearTuple(node->cleanedUpSlot);
EvalPlanQualEnd(&node->mt_epqstate);
ExecEndNode(outerPlanState(node));
EndPlanStateGpmonPkt(&node->ps);
}
Expand Down
24 changes: 17 additions & 7 deletions src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4100,6 +4100,7 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
DML *dml = MakeNode(DML);
Plan *plan = &(dml->plan);
AclMode acl_mode = ACL_NO_RIGHTS;
BOOL isSplit = phy_dml_dxlop->FSplit();

switch (phy_dml_dxlop->GetDmlOpType())
{
Expand Down Expand Up @@ -4186,14 +4187,25 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
dml_target_list = target_list_with_dropped_cols;
}

// Extract column numbers of the action and ctid columns from the
// target list.
dml->actionColIdx = AddTargetEntryForColId(&dml_target_list, &child_context,
phy_dml_dxlop->ActionColId(),
true /*is_resjunk*/);
// Doesn't needed for in place update
if (isSplit || CMD_UPDATE != m_cmd_type)
{
// Extract column numbers of the action and ctid columns from the
// target list.
dml->actionColIdx = AddTargetEntryForColId(
&dml_target_list, &child_context, phy_dml_dxlop->ActionColId(),
true /*is_resjunk*/);
GPOS_ASSERT(0 != dml->actionColIdx);
}
else
{
dml->actionColIdx = 0;
}

dml->ctidColIdx = AddTargetEntryForColId(&dml_target_list, &child_context,
phy_dml_dxlop->GetCtIdColId(),
true /*is_resjunk*/);

if (phy_dml_dxlop->IsOidsPreserved())
{
dml->tupleoidColIdx = AddTargetEntryForColId(
Expand All @@ -4205,8 +4217,6 @@ CTranslatorDXLToPlStmt::TranslateDXLDml(
dml->tupleoidColIdx = 0;
}

GPOS_ASSERT(0 != dml->actionColIdx);

plan->targetlist = dml_target_list;

plan->lefttree = child_plan;
Expand Down
4 changes: 2 additions & 2 deletions src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ update t1 set b = c;
<dxl:OptimizerConfig>
<dxl:EnumeratorConfig Id="0" PlanSamples="0" CostThreshold="0"/>
<dxl:StatisticsConfig DampingFactorFilter="0.750000" DampingFactorJoin="0.010000" DampingFactorGroupBy="0.750000" MaxStatsBuckets="100"/>
<dxl:CTEConfig CTEInliningCutoff="0"/>
<dxl:CTEConfig CTEInliningCutoff="0"/>
<dxl:WindowOids RowNumber="7000" Rank="7001"/>
<dxl:CostModelConfig CostModelType="1" SegmentsForCosting="3">
<dxl:CostParams>
Expand Down Expand Up @@ -216,7 +216,7 @@ update t1 set b = c;
</dxl:LogicalUpdate>
</dxl:Query>
<dxl:Plan Id="0" SpaceSize="1">
<dxl:DMLUpdate Columns="0,1,2" ActionCol="10" CtidCol="3" SegmentIdCol="9" PreserveOids="false">
<dxl:DMLUpdate Columns="0,1,2" ActionCol="10" CtidCol="3" SegmentIdCol="9" IsSplitUpdate="true">
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.067764" Rows="1.000000" Width="1"/>
</dxl:Properties>
Expand Down
127 changes: 42 additions & 85 deletions src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp
Original file line number Diff line number Diff line change
Expand Up @@ -294,17 +294,17 @@
</dxl:LogicalUpdate>
</dxl:Query>
<dxl:Plan Id="0" SpaceSize="1">
<dxl:DMLUpdate Columns="0,1,2,3" ActionCol="12" CtidCol="4" SegmentIdCol="10" PreserveOids="false">
<dxl:DMLUpdate Columns="0,11,2,3" ActionCol="12" CtidCol="4" SegmentIdCol="10" IsSplitUpdate="false" PreserveOids="false">
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.117383" Rows="1.000000" Width="1"/>
<dxl:Cost StartupCost="0" TotalCost="431.050903" Rows="1.000000" Width="1"/>
</dxl:Properties>
<dxl:DirectDispatchInfo/>
<dxl:ProjList>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:Ident ColId="11" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
Expand All @@ -330,14 +330,14 @@
</dxl:TableDescriptor>
<dxl:Assert ErrorCode="23514">
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.000195" Rows="2.000000" Width="30"/>
<dxl:Cost StartupCost="0" TotalCost="431.000121" Rows="1.000000" Width="26"/>
</dxl:Properties>
<dxl:ProjList>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:Ident ColId="11" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
Expand All @@ -351,9 +351,6 @@
<dxl:ProjElem ColId="10" Alias="gp_segment_id">
<dxl:Ident ColId="10" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="12" Alias="ColRef_0012">
<dxl:Ident ColId="12" ColName="ColRef_0012" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
</dxl:ProjList>
<dxl:AssertConstraintList>
<dxl:AssertConstraint ErrorMessage="Check constraint r_check for table r was violated">
Expand All @@ -377,15 +374,12 @@
</dxl:AssertConstraintList>
<dxl:Assert ErrorCode="23502">
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.000165" Rows="2.000000" Width="30"/>
<dxl:Cost StartupCost="0" TotalCost="431.000108" Rows="1.000000" Width="26"/>
</dxl:Properties>
<dxl:ProjList>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
Expand All @@ -398,8 +392,8 @@
<dxl:ProjElem ColId="10" Alias="gp_segment_id">
<dxl:Ident ColId="10" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="12" Alias="ColRef_0012">
<dxl:Ident ColId="12" ColName="ColRef_0012" TypeMdid="0.23.1.0"/>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:Ident ColId="11" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
</dxl:ProjList>
<dxl:AssertConstraintList>
Expand All @@ -411,17 +405,17 @@
</dxl:Not>
</dxl:AssertConstraint>
</dxl:AssertConstraintList>
<dxl:Split DeleteColumns="0,1,2,3" InsertColumns="0,11,2,3" ActionCol="12" CtidCol="4" SegmentIdCol="10" PreserveOids="false">
<dxl:Result>
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.000135" Rows="2.000000" Width="34"/>
<dxl:Cost StartupCost="0" TotalCost="431.000095" Rows="1.000000" Width="26"/>
</dxl:Properties>
<dxl:ProjList>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:ConstValue TypeMdid="0.23.1.0" Value="2"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
Expand All @@ -434,90 +428,53 @@
<dxl:ProjElem ColId="10" Alias="gp_segment_id">
<dxl:Ident ColId="10" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:Ident ColId="11" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="12" Alias="ColRef_0012">
<dxl:DMLAction/>
</dxl:ProjElem>
</dxl:ProjList>
<dxl:Result>
<dxl:Filter/>
<dxl:OneTimeFilter/>
<dxl:TableScan>
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.000101" Rows="1.000000" Width="30"/>
<dxl:Cost StartupCost="0" TotalCost="431.000082" Rows="1.000000" Width="26"/>
</dxl:Properties>
<dxl:ProjList>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="3" Alias="d">
<dxl:Ident ColId="3" ColName="d" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="11" Alias="b">
<dxl:ConstValue TypeMdid="0.23.1.0" Value="2"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="4" Alias="ctid">
<dxl:Ident ColId="4" ColName="ctid" TypeMdid="0.27.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="10" Alias="gp_segment_id">
<dxl:Ident ColId="10" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
</dxl:ProjList>
<dxl:Filter/>
<dxl:OneTimeFilter/>
<dxl:TableScan>
<dxl:Properties>
<dxl:Cost StartupCost="0" TotalCost="431.000086" Rows="1.000000" Width="30"/>
</dxl:Properties>
<dxl:ProjList>
<dxl:ProjElem ColId="0" Alias="a">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="1" Alias="b">
<dxl:Ident ColId="1" ColName="b" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="2" Alias="c">
<dxl:Ident ColId="2" ColName="c" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="3" Alias="d">
<dxl:Ident ColId="3" ColName="d" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="4" Alias="ctid">
<dxl:Ident ColId="4" ColName="ctid" TypeMdid="0.27.1.0"/>
</dxl:ProjElem>
<dxl:ProjElem ColId="10" Alias="gp_segment_id">
<dxl:Ident ColId="10" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:ProjElem>
</dxl:ProjList>
<dxl:Filter>
<dxl:Comparison ComparisonOperator="&gt;" OperatorMdid="0.521.1.0">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
<dxl:ConstValue TypeMdid="0.23.1.0" Value="1"/>
</dxl:Comparison>
</dxl:Filter>
<dxl:TableDescriptor Mdid="6.17005.1.1" TableName="r">
<dxl:Columns>
<dxl:Column ColId="0" Attno="1" ColName="a" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="1" Attno="2" ColName="b" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="2" Attno="3" ColName="c" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="3" Attno="4" ColName="d" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="4" Attno="-1" ColName="ctid" TypeMdid="0.27.1.0"/>
<dxl:Column ColId="5" Attno="-3" ColName="xmin" TypeMdid="0.28.1.0"/>
<dxl:Column ColId="6" Attno="-4" ColName="cmin" TypeMdid="0.29.1.0"/>
<dxl:Column ColId="7" Attno="-5" ColName="xmax" TypeMdid="0.28.1.0"/>
<dxl:Column ColId="8" Attno="-6" ColName="cmax" TypeMdid="0.29.1.0"/>
<dxl:Column ColId="9" Attno="-7" ColName="tableoid" TypeMdid="0.26.1.0"/>
<dxl:Column ColId="10" Attno="-8" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:Columns>
</dxl:TableDescriptor>
</dxl:TableScan>
</dxl:Result>
</dxl:Split>
<dxl:Filter>
<dxl:Comparison ComparisonOperator="&gt;" OperatorMdid="0.521.1.0">
<dxl:Ident ColId="0" ColName="a" TypeMdid="0.23.1.0"/>
<dxl:ConstValue TypeMdid="0.23.1.0" Value="1"/>
</dxl:Comparison>
</dxl:Filter>
<dxl:TableDescriptor Mdid="6.17005.1.1" TableName="r">
<dxl:Columns>
<dxl:Column ColId="0" Attno="1" ColName="a" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="1" Attno="2" ColName="b" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="2" Attno="3" ColName="c" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="3" Attno="4" ColName="d" TypeMdid="0.23.1.0"/>
<dxl:Column ColId="4" Attno="-1" ColName="ctid" TypeMdid="0.27.1.0"/>
<dxl:Column ColId="5" Attno="-3" ColName="xmin" TypeMdid="0.28.1.0"/>
<dxl:Column ColId="6" Attno="-4" ColName="cmin" TypeMdid="0.29.1.0"/>
<dxl:Column ColId="7" Attno="-5" ColName="xmax" TypeMdid="0.28.1.0"/>
<dxl:Column ColId="8" Attno="-6" ColName="cmax" TypeMdid="0.29.1.0"/>
<dxl:Column ColId="9" Attno="-7" ColName="tableoid" TypeMdid="0.26.1.0"/>
<dxl:Column ColId="10" Attno="-8" ColName="gp_segment_id" TypeMdid="0.23.1.0"/>
</dxl:Columns>
</dxl:TableDescriptor>
</dxl:TableScan>
</dxl:Result>
</dxl:Assert>
</dxl:Assert>
</dxl:DMLUpdate>
Expand Down
Loading

0 comments on commit a02d221

Please sign in to comment.