Skip to content

Commit bc48672

Browse files
committed
ORCA: allow partition table use the append node
1 parent 5804930 commit bc48672

File tree

14 files changed

+327
-5
lines changed

14 files changed

+327
-5
lines changed

src/backend/gpopt/config/CConfigParamMapping.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -301,15 +301,18 @@ CConfigParamMapping::SConfigMappingElem CConfigParamMapping::m_elements[] = {
301301
{EopttraceEnableUseDistributionInDQA,
302302
&optimizer_enable_use_distribution_in_dqa,
303303
false, // m_negate_param
304-
GPOS_WSZ_LIT(
305-
"Enable use the distribution key in DQA")},
304+
GPOS_WSZ_LIT("Enable use the distribution key in DQA")},
306305
{EopttraceDisableInnerHashJoin, &optimizer_enable_hashjoin,
307306
true, // m_negate_param
308307
GPOS_WSZ_LIT("Explore hash join alternatives")},
309308
{EopttraceDisableInnerNLJ, &optimizer_enable_nljoin,
310309
true, // m_negate_param
311310
GPOS_WSZ_LIT("Enable nested loop join alternatives")},
312311

312+
{EopttraceDisableDynamicTableScan, &optimizer_disable_dynamic_table_scan,
313+
false, // m_negate_param
314+
GPOS_WSZ_LIT(
315+
"Disable the dynamic seq/bitmap/index scan in partition table")},
313316
};
314317

315318
//---------------------------------------------------------------------------

src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -3921,6 +3921,31 @@ CTranslatorDXLToPlStmt::TranslateDXLAppend(
39213921
GPOS_ASSERT(EdxlappendIndexFirstChild < arity);
39223922
append->appendplans = NIL;
39233923

3924+
// translate table descriptor into a range table entry
3925+
CDXLPhysicalAppend *phy_append_dxlop =
3926+
CDXLPhysicalAppend::Cast(append_dxlnode->GetOperator());
3927+
3928+
// If this append was create from a DynamicTableScan node in ORCA, it will
3929+
// contain the table descriptor of the root partitioned table. Add that to
3930+
// the range table in the PlStmt.
3931+
if (phy_append_dxlop->GetScanId() != gpos::ulong_max)
3932+
{
3933+
GPOS_ASSERT(nullptr != phy_append_dxlop->GetDXLTableDesc());
3934+
3935+
// translation context for column mappings in the base relation
3936+
CDXLTranslateContextBaseTable base_table_context(m_mp);
3937+
3938+
(void) ProcessDXLTblDescr(phy_append_dxlop->GetDXLTableDesc(),
3939+
&base_table_context);
3940+
3941+
OID oid_type =
3942+
CMDIdGPDB::CastMdid(m_md_accessor->PtMDType<IMDTypeInt4>()->MDId())
3943+
->Oid();
3944+
append->join_prune_paramids =
3945+
TranslateJoinPruneParamids(phy_append_dxlop->GetSelectorIds(),
3946+
oid_type, m_dxl_to_plstmt_context);
3947+
}
3948+
39243949
// translate children
39253950
CDXLTranslateContext child_context(m_mp, false,
39263951
output_context->GetColIdToParamIdMap());

src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorExprToDXL.h

+7
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,13 @@ class CTranslatorExprToDXL
313313
CDistributionSpecArray *pdrgpdsBaseTables,
314314
ULONG *pulNonGatherMotions, BOOL *pfDML);
315315

316+
// translate a dynamic scan to append
317+
template <class PhysicalScanType>
318+
CDXLNode *PdxlnDynamicScanToAppend(
319+
CExpression *pexprDTS, CColRefArray *colref_array,
320+
CDistributionSpecArray *pdrgpdsBaseTables, CExpression *pexprScalarCond,
321+
CDXLPhysicalProperties *dxl_properties);
322+
316323
// translate a dynamic table scan
317324
CDXLNode *PdxlnDynamicTableScan(CExpression *pexprDTS,
318325
CColRefArray *colref_array,

src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp

+148
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,11 @@ CTranslatorExprToDXL::PdxlnDynamicTableScan(
13511351
GPOS_ASSERT(nullptr != pexprDTS);
13521352
GPOS_ASSERT_IFF(nullptr != pexprScalarCond, nullptr != dxl_properties);
13531353

1354+
if (GPOS_FTRACE(EopttraceDisableDynamicTableScan)) {
1355+
return PdxlnDynamicScanToAppend<CPhysicalDynamicTableScan>(pexprDTS, colref_array,
1356+
pdrgpdsBaseTables, pexprScalarCond, dxl_properties);
1357+
}
1358+
13541359
CPhysicalDynamicTableScan *popDTS =
13551360
CPhysicalDynamicTableScan::PopConvert(pexprDTS->Pop());
13561361
CColRefArray *pdrgpcrOutput = popDTS->PdrgpcrOutput();
@@ -1429,6 +1434,143 @@ CTranslatorExprToDXL::PdxlnDynamicTableScan(
14291434
return pdxlnDTS;
14301435
}
14311436

1437+
1438+
template <class PhysicalScanType>
1439+
CDXLNode *
1440+
CTranslatorExprToDXL::PdxlnDynamicScanToAppend(CExpression *pexprDTS,
1441+
CColRefArray *colref_array,
1442+
CDistributionSpecArray *pdrgpdsBaseTables,
1443+
CExpression *pexprScalarCond,
1444+
CDXLPhysicalProperties *dxl_properties) {
1445+
1446+
PhysicalScanType *popDTS =
1447+
PhysicalScanType::PopConvert(pexprDTS->Pop());
1448+
1449+
ULongPtrArray *selector_ids = GPOS_NEW(m_mp) ULongPtrArray(m_mp);
1450+
CPartitionPropagationSpec *pps_reqd =
1451+
pexprDTS->Prpp()->Pepp()->PppsRequired();
1452+
if (pps_reqd->Contains(popDTS->ScanId()))
1453+
{
1454+
const CBitSet *bs = pps_reqd->SelectorIds(popDTS->ScanId());
1455+
CBitSetIter bsi(*bs);
1456+
for (ULONG ul = 0; bsi.Advance(); ul++)
1457+
{
1458+
selector_ids->Append(GPOS_NEW(m_mp) ULONG(bsi.Bit()));
1459+
}
1460+
}
1461+
1462+
// construct plan costs
1463+
CDXLPhysicalProperties *pdxlpropDTS = GetProperties(pexprDTS);
1464+
1465+
if (nullptr != dxl_properties)
1466+
{
1467+
CWStringDynamic *rows_out_str = GPOS_NEW(m_mp) CWStringDynamic(
1468+
m_mp,
1469+
dxl_properties->GetDXLOperatorCost()->GetRowsOutStr()->GetBuffer());
1470+
CWStringDynamic *pstrCost = GPOS_NEW(m_mp)
1471+
CWStringDynamic(m_mp, dxl_properties->GetDXLOperatorCost()
1472+
->GetTotalCostStr()
1473+
->GetBuffer());
1474+
1475+
pdxlpropDTS->GetDXLOperatorCost()->SetRows(rows_out_str);
1476+
pdxlpropDTS->GetDXLOperatorCost()->SetCost(pstrCost);
1477+
dxl_properties->Release();
1478+
}
1479+
GPOS_ASSERT(nullptr != pexprDTS->Prpp());
1480+
1481+
// construct projection list for top-level Append node
1482+
CColRefSet *pcrsOutput = pexprDTS->Prpp()->PcrsRequired();
1483+
CDXLNode *pdxlnPrLAppend = PdxlnProjList(pcrsOutput, colref_array);
1484+
CDXLTableDescr *root_dxl_table_descr = MakeDXLTableDescr(
1485+
popDTS->Ptabdesc(), popDTS->PdrgpcrOutput(), pexprDTS->Prpp());
1486+
1487+
// Construct the Append node - even when there is only one child partition.
1488+
// This is done for two reasons:
1489+
// * Dynamic partition pruning
1490+
// Even if one partition is present in the statically pruned plan, we could
1491+
// still dynamically prune it away. This needs an Append node.
1492+
// * Col mappings issues
1493+
// When the first selected child partition's cols have different types/order
1494+
// than the root partition, we can no longer re-use the colrefs of the root
1495+
// partition, since colrefs are immutable. Thus, we create new colrefs for
1496+
// this partition. But, if there is no Append (in case of just one selected
1497+
// partition), then we also go through update all references above the DTS
1498+
// with the new colrefs. For simplicity, we decided to keep the Append
1499+
// around to maintain this projection (mapping) from the old root colrefs
1500+
// to the first selected partition colrefs.
1501+
//
1502+
// GPDB_12_MERGE_FIXME: An Append on a single TableScan can be removed in
1503+
// CTranslatorDXLToPlstmt since these points do not apply there.
1504+
CDXLNode *pdxlnAppend = GPOS_NEW(m_mp) CDXLNode(
1505+
m_mp,
1506+
GPOS_NEW(m_mp) CDXLPhysicalAppend(m_mp, false, false, popDTS->ScanId(),
1507+
root_dxl_table_descr, selector_ids));
1508+
pdxlnAppend->SetProperties(pdxlpropDTS);
1509+
pdxlnAppend->AddChild(pdxlnPrLAppend);
1510+
pdxlnAppend->AddChild(PdxlnFilter(nullptr));
1511+
1512+
IMdIdArray *part_mdids = popDTS->GetPartitionMdids();
1513+
for (ULONG ul = 0; ul < part_mdids->Size(); ++ul)
1514+
{
1515+
IMDId *part_mdid = (*part_mdids)[ul];
1516+
const IMDRelation *part = m_pmda->RetrieveRel(part_mdid);
1517+
1518+
CTableDescriptor *part_tabdesc =
1519+
MakeTableDescForPart(part, popDTS->Ptabdesc());
1520+
1521+
// Create new colrefs for the child partition. The ColRefs from root
1522+
// DTS, which may be used in any parent node, can no longer be exported
1523+
// by a child of the Append node. Thus it is exported by the Append
1524+
// node itself, and new colrefs are created here.
1525+
CColRefArray *part_colrefs = GPOS_NEW(m_mp) CColRefArray(m_mp);
1526+
for (ULONG ul_col = 0; ul_col < part_tabdesc->ColumnCount(); ++ul_col)
1527+
{
1528+
const CColumnDescriptor *cd = part_tabdesc->Pcoldesc(ul_col);
1529+
CColRef *cr = m_pcf->PcrCreate(cd->RetrieveType(),
1530+
cd->TypeModifier(), cd->Name());
1531+
part_colrefs->Append(cr);
1532+
}
1533+
1534+
CDXLTableDescr *dxl_table_descr =
1535+
MakeDXLTableDescr(part_tabdesc, part_colrefs, pexprDTS->Prpp());
1536+
part_tabdesc->Release();
1537+
1538+
CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode(
1539+
m_mp, GPOS_NEW(m_mp) CDXLPhysicalTableScan(m_mp, dxl_table_descr));
1540+
1541+
// GPDB_12_MERGE_FIXME: Compute stats & properties per scan
1542+
pdxlpropDTS->AddRef();
1543+
dxlnode->SetProperties(pdxlpropDTS);
1544+
1545+
// ColRef -> index in child table desc (per partition)
1546+
auto root_col_mapping = (*popDTS->GetRootColMappingPerPart())[ul];
1547+
1548+
// construct projection list, re-ordered to match root DTS
1549+
CDXLNode *pdxlnPrL = PdxlnProjListForChildPart(
1550+
root_col_mapping, part_colrefs, pcrsOutput, colref_array);
1551+
dxlnode->AddChild(pdxlnPrL); // project list
1552+
1553+
// construct the filter
1554+
CDXLNode *filter_dxlnode = PdxlnFilter(
1555+
PdxlnCondForChildPart(root_col_mapping, part_colrefs,
1556+
popDTS->PdrgpcrOutput(), pexprScalarCond));
1557+
dxlnode->AddChild(filter_dxlnode); // filter
1558+
1559+
// add to the other scans under the created Append node
1560+
pdxlnAppend->AddChild(dxlnode);
1561+
1562+
// cleanup
1563+
part_colrefs->Release();
1564+
}
1565+
1566+
CDistributionSpec *pds = pexprDTS->GetDrvdPropPlan()->Pds();
1567+
pds->AddRef();
1568+
pdrgpdsBaseTables->Append(pds);
1569+
1570+
GPOS_ASSERT(pdxlnAppend);
1571+
return pdxlnAppend;
1572+
}
1573+
14321574
//---------------------------------------------------------------------------
14331575
// @function:
14341576
// CTranslatorExprToDXL::PdxlnDynamicBitmapTableScan
@@ -1763,6 +1905,11 @@ CTranslatorExprToDXL::PdxlnDynamicForeignScan(
17631905
GPOS_ASSERT(nullptr != pexprDFS);
17641906
GPOS_ASSERT_IFF(nullptr != pexprScalarCond, nullptr != dxl_properties);
17651907

1908+
if (GPOS_FTRACE(EopttraceDisableDynamicTableScan)) {
1909+
return PdxlnDynamicScanToAppend<CPhysicalDynamicForeignScan>(pexprDFS, colref_array,
1910+
pdrgpdsBaseTables, pexprScalarCond, dxl_properties);
1911+
}
1912+
17661913
CPhysicalDynamicForeignScan *popDFS =
17671914
CPhysicalDynamicForeignScan::PopConvert(pexprDFS->Pop());
17681915
CColRefArray *pdrgpcrOutput = popDFS->PdrgpcrOutput();
@@ -1841,6 +1988,7 @@ CTranslatorExprToDXL::PdxlnDynamicForeignScan(
18411988

18421989
return pdxlnDFS;
18431990
}
1991+
18441992
//---------------------------------------------------------------------------
18451993
// @function:
18461994
// CTranslatorExprToDXL::PdxlnResult

src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLPhysicalAppend.h

+41
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,60 @@ class CDXLPhysicalAppend : public CDXLPhysical
4949
// TODO: - Apr 12, 2011; find a better name (and comments) for this variable
5050
BOOL m_is_zapped = false;
5151

52+
// scan id from the CPhysicalDynamicTableScan (a.k.a part_index_id)
53+
// when m_scan_id != gpos::ulong_max
54+
ULONG m_scan_id = gpos::ulong_max;
55+
56+
// table descr of the root partitioned table (when translated from a CPhysicalDynamicTableScan)
57+
CDXLTableDescr *m_dxl_table_descr = nullptr;
58+
59+
ULongPtrArray *m_selector_ids = nullptr;
60+
5261
public:
5362
CDXLPhysicalAppend(const CDXLPhysicalAppend &) = delete;
5463

5564
// ctor/dtor
5665
CDXLPhysicalAppend(CMemoryPool *mp, BOOL fIsTarget, BOOL fIsZapped);
5766

67+
// ctor for partitioned table scan
68+
CDXLPhysicalAppend(CMemoryPool *mp, BOOL fIsTarget, BOOL fIsZapped,
69+
ULONG scan_id, CDXLTableDescr *dxl_table_desc,
70+
ULongPtrArray *selector_ids);
71+
72+
// dtor
73+
~CDXLPhysicalAppend() override;
74+
5875
// accessors
5976
Edxlopid GetDXLOperator() const override;
6077
const CWStringConst *GetOpNameStr() const override;
6178

6279
BOOL IsUsedInUpdDel() const;
6380
BOOL IsZapped() const;
6481

82+
CDXLTableDescr *
83+
GetDXLTableDesc() const
84+
{
85+
return m_dxl_table_descr;
86+
}
87+
88+
void
89+
SetDXLTableDesc(CDXLTableDescr *dxl_table_desc)
90+
{
91+
m_dxl_table_descr = dxl_table_desc;
92+
}
93+
94+
ULONG
95+
GetScanId() const
96+
{
97+
return m_scan_id;
98+
}
99+
100+
const ULongPtrArray *
101+
GetSelectorIds() const
102+
{
103+
return m_selector_ids;
104+
}
105+
65106
// serialize operator in DXL format
66107
void SerializeToDXL(CXMLSerializer *xml_serializer,
67108
const CDXLNode *dxlnode) const override;

src/backend/gporca/libnaucrates/include/naucrates/dxl/xml/dxltokens.h

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ enum Edxltoken
131131

132132
EdxltokenDuplicateSensitive,
133133

134+
EdxltokenPartIndexId,
135+
EdxltokenPartIndexIdPrintable,
134136
EdxltokenSegmentIdCol,
135137

136138
EdxltokenScalar,

src/backend/gporca/libnaucrates/include/naucrates/traceflags/traceflags.h

+3
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ enum EOptTraceFlag
229229
// Ordered Agg
230230
EopttraceDisableOrderedAgg = 103047,
231231

232+
// Disable dynamic seq/bitmap/index scan
233+
EopttraceDisableDynamicTableScan = 103048,
234+
232235
///////////////////////////////////////////////////////
233236
///////////////////// statistics flags ////////////////
234237
//////////////////////////////////////////////////////

src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,20 @@ CDXLOperatorFactory::MakeDXLAppend(CDXLMemoryManager *dxl_memory_manager,
366366
EdxltokenAppendIsZapped,
367367
EdxltokenPhysicalAppend);
368368

369-
return GPOS_NEW(mp) CDXLPhysicalAppend(mp, is_target, is_zapped);
369+
ULONG scan_id = ExtractConvertAttrValueToUlong(dxl_memory_manager, attrs, EdxltokenPartIndexId,
370+
EdxltokenPhysicalAppend, true /* is_optional */,
371+
gpos::ulong_max /* default_value */);
372+
373+
ULongPtrArray *selector_ids = nullptr;
374+
if (scan_id != gpos::ulong_max)
375+
{
376+
selector_ids = ExtractConvertValuesToArray(dxl_memory_manager, attrs,
377+
EdxltokenSelectorIds,
378+
EdxltokenPhysicalAppend);
379+
}
380+
381+
return GPOS_NEW(mp) CDXLPhysicalAppend(mp, is_target, is_zapped, scan_id,
382+
nullptr, selector_ids);
370383
}
371384

372385
//---------------------------------------------------------------------------

src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalAppend.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ CDXLPhysicalAppend::CDXLPhysicalAppend(CMemoryPool *mp, BOOL fIsTarget,
3434
{
3535
}
3636

37+
CDXLPhysicalAppend::CDXLPhysicalAppend(CMemoryPool *mp, BOOL fIsTarget,
38+
BOOL fIsZapped, ULONG scan_id,
39+
CDXLTableDescr *dxl_table_desc,
40+
ULongPtrArray *selector_ids)
41+
: CDXLPhysical(mp),
42+
m_used_in_upd_del(fIsTarget),
43+
m_is_zapped(fIsZapped),
44+
m_scan_id(scan_id),
45+
m_dxl_table_descr(dxl_table_desc),
46+
m_selector_ids(selector_ids)
47+
{
48+
}
49+
50+
CDXLPhysicalAppend::~CDXLPhysicalAppend()
51+
{
52+
CRefCount::SafeRelease(m_dxl_table_descr);
53+
CRefCount::SafeRelease(m_selector_ids);
54+
}
55+
3756
//---------------------------------------------------------------------------
3857
// @function:
3958
// CDXLPhysicalAppend::GetDXLOperator
@@ -113,9 +132,28 @@ CDXLPhysicalAppend::SerializeToDXL(CXMLSerializer *xml_serializer,
113132
xml_serializer->AddAttribute(
114133
CDXLTokens::GetDXLTokenStr(EdxltokenAppendIsZapped), m_is_zapped);
115134

135+
if (m_scan_id != gpos::ulong_max)
136+
{
137+
xml_serializer->AddAttribute(
138+
CDXLTokens::GetDXLTokenStr(EdxltokenPartIndexId), m_scan_id);
139+
140+
CWStringDynamic *serialized_selector_ids =
141+
CDXLUtils::Serialize(m_mp, m_selector_ids);
142+
xml_serializer->AddAttribute(
143+
CDXLTokens::GetDXLTokenStr(EdxltokenSelectorIds),
144+
serialized_selector_ids);
145+
GPOS_DELETE(serialized_selector_ids);
146+
}
116147
// serialize properties
117148
dxlnode->SerializePropertiesToDXL(xml_serializer);
118149

150+
if (m_dxl_table_descr != nullptr)
151+
{
152+
GPOS_ASSERT(m_scan_id != gpos::ulong_max);
153+
m_dxl_table_descr->SerializeToDXL(xml_serializer);
154+
}
155+
156+
119157
// serialize children
120158
dxlnode->SerializeChildrenToDXL(xml_serializer);
121159

0 commit comments

Comments
 (0)