Skip to content

Commit 47ccbe2

Browse files
authored
Implement cbo join tree -> yt join tree converter (#1730)
1 parent e09e4a9 commit 47ccbe2

File tree

3 files changed

+125
-27
lines changed

3 files changed

+125
-27
lines changed

ydb/library/yql/providers/yt/provider/ut/yql_yt_cbo_ut.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,50 @@ Y_UNIT_TEST(BuildOptimizerTree2TablesComplexLabel) {
119119
UNIT_ASSERT_VALUES_EQUAL(right->Stats->Nrows, 10000);
120120
}
121121

122+
Y_UNIT_TEST(BuildYtJoinTree2Tables) {
123+
TExprContext exprCtx;
124+
auto tree = MakeOp({"c", "c_nationkey"}, {"n", "n_nationkey"}, {"c", "n"}, exprCtx);
125+
tree->Left = MakeLeaf({"c"}, {"c"}, 100000, 12333, exprCtx);
126+
tree->Right = MakeLeaf({"n"}, {"n"}, 1000, 1233, exprCtx);
127+
128+
std::shared_ptr<IBaseOptimizerNode> resultTree;
129+
std::shared_ptr<IProviderContext> resultCtx;
130+
BuildOptimizerJoinTree(resultTree, resultCtx, tree);
131+
132+
auto joinTree = BuildYtJoinTree(resultTree, exprCtx, {});
133+
134+
UNIT_ASSERT(AreSimilarTrees(joinTree, tree));
135+
}
136+
137+
Y_UNIT_TEST(BuildYtJoinTree2TablesComplexLabel) {
138+
TExprContext exprCtx;
139+
auto tree = MakeOp({"c", "c_nationkey"}, {"n", "n_nationkey"}, {"c", "n", "e"}, exprCtx);
140+
tree->Left = MakeLeaf({"c"}, {"c"}, 1000000, 1233333, exprCtx);
141+
tree->Right = MakeLeaf({"n"}, {"n", "e"}, 10000, 12333, exprCtx);
142+
143+
std::shared_ptr<IBaseOptimizerNode> resultTree;
144+
std::shared_ptr<IProviderContext> resultCtx;
145+
BuildOptimizerJoinTree(resultTree, resultCtx, tree);
146+
auto joinTree = BuildYtJoinTree(resultTree, exprCtx, {});
147+
148+
UNIT_ASSERT(AreSimilarTrees(joinTree, tree));
149+
}
150+
151+
Y_UNIT_TEST(BuildYtJoinTree2TablesTableIn2Rels)
152+
{
153+
TExprContext exprCtx;
154+
auto tree = MakeOp({"c", "c_nationkey"}, {"n", "n_nationkey"}, {"c", "n", "c"}, exprCtx);
155+
tree->Left = MakeLeaf({"c"}, {"c"}, 1000000, 1233333, exprCtx);
156+
tree->Right = MakeLeaf({"n"}, {"n", "c"}, 10000, 12333, exprCtx);
157+
158+
std::shared_ptr<IBaseOptimizerNode> resultTree;
159+
std::shared_ptr<IProviderContext> resultCtx;
160+
BuildOptimizerJoinTree(resultTree, resultCtx, tree);
161+
auto joinTree = BuildYtJoinTree(resultTree, exprCtx, {});
162+
163+
UNIT_ASSERT(AreSimilarTrees(joinTree, tree));
164+
}
165+
122166
#define ADD_TEST(Name) \
123167
Y_UNIT_TEST(Name ## _PG) { \
124168
Name(ECostBasedOptimizerType::PG); \

ydb/library/yql/providers/yt/provider/yql_yt_join_impl.h

+2
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,7 @@ struct IBaseOptimizerNode;
7070
struct IProviderContext;
7171

7272
void BuildOptimizerJoinTree(std::shared_ptr<IBaseOptimizerNode>& tree, std::shared_ptr<IProviderContext>& ctx, TYtJoinNodeOp::TPtr op);
73+
TYtJoinNode::TPtr BuildYtJoinTree(std::shared_ptr<IBaseOptimizerNode> node, TExprContext& ctx, TPositionHandle pos);
74+
bool AreSimilarTrees(TYtJoinNode::TPtr node1, TYtJoinNode::TPtr node2);
7375

7476
}

ydb/library/yql/providers/yt/provider/yql_yt_join_reorder.cpp

+79-27
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,6 @@ namespace NYql {
1212

1313
namespace {
1414

15-
bool AreSimilarTrees(TYtJoinNode::TPtr node1, TYtJoinNode::TPtr node2) {
16-
if (node1 == node2) {
17-
return true;
18-
}
19-
if (node1 && !node2) {
20-
return false;
21-
}
22-
if (node2 && !node1) {
23-
return false;
24-
}
25-
if (node1->Scope != node2->Scope) {
26-
return false;
27-
}
28-
auto opLeft = dynamic_cast<TYtJoinNodeOp*>(node1.Get());
29-
auto opRight = dynamic_cast<TYtJoinNodeOp*>(node2.Get());
30-
if (opLeft && opRight) {
31-
return AreSimilarTrees(opLeft->Left, opRight->Left)
32-
&& AreSimilarTrees(opLeft->Right, opRight->Right);
33-
} else if (!opLeft && !opRight) {
34-
return true;
35-
} else {
36-
return false;
37-
}
38-
}
39-
4015
void DebugPrint(TYtJoinNode::TPtr node, TExprContext& ctx, int level) {
4116
auto* op = dynamic_cast<TYtJoinNodeOp*>(node.Get());
4217
auto printScope = [](const TVector<TString>& scope) -> TString {
@@ -409,6 +384,16 @@ class TJoinReorderer {
409384
IOptimizer::TOutput Result;
410385
};
411386

387+
class TYtRelOptimizerNode: public TRelOptimizerNode {
388+
public:
389+
TYtRelOptimizerNode(TString label, std::shared_ptr<TOptimizerStatistics> stats, TYtJoinNodeLeaf* leaf)
390+
: TRelOptimizerNode(std::move(label), std::move(stats))
391+
, OriginalLeaf(leaf)
392+
{ }
393+
394+
TYtJoinNodeLeaf* OriginalLeaf;
395+
};
396+
412397
class TOptimizerTreeBuilder
413398
{
414399
public:
@@ -487,8 +472,8 @@ class TOptimizerTreeBuilder
487472
}
488473
}
489474

490-
return std::make_shared<TRelOptimizerNode>(
491-
std::move(label), std::move(stat)
475+
return std::make_shared<TYtRelOptimizerNode>(
476+
std::move(label), std::move(stat), leaf
492477
);
493478
}
494479

@@ -498,13 +483,80 @@ class TOptimizerTreeBuilder
498483
TYtJoinNodeOp::TPtr InputTree;
499484
};
500485

486+
TYtJoinNode::TPtr BuildYtJoinTree(std::shared_ptr<IBaseOptimizerNode> node, TVector<TString>& scope, TExprContext& ctx, TPositionHandle pos) {
487+
if (node->Kind == RelNodeType) {
488+
auto* leaf = static_cast<TYtRelOptimizerNode*>(node.get())->OriginalLeaf;
489+
scope.insert(scope.end(), leaf->Scope.begin(), leaf->Scope.end());
490+
return leaf;
491+
} else if (node->Kind == JoinNodeType) {
492+
auto ret = MakeIntrusive<TYtJoinNodeOp>();
493+
auto* op = static_cast<TJoinOptimizerNode*>(node.get());
494+
ret->JoinKind = ctx.NewAtom(pos, ConvertToJoinString(op->JoinType));
495+
TVector<TExprNodePtr> leftLabel, rightLabel;
496+
leftLabel.reserve(op->JoinConditions.size() * 2);
497+
rightLabel.reserve(op->JoinConditions.size() * 2);
498+
for (auto& [left, right] : op->JoinConditions) {
499+
leftLabel.emplace_back(ctx.NewAtom(pos, left.RelName));
500+
leftLabel.emplace_back(ctx.NewAtom(pos, left.AttributeName));
501+
502+
rightLabel.emplace_back(ctx.NewAtom(pos, right.RelName));
503+
rightLabel.emplace_back(ctx.NewAtom(pos, right.AttributeName));
504+
}
505+
ret->LeftLabel = Build<TCoAtomList>(ctx, pos)
506+
.Add(leftLabel)
507+
.Done()
508+
.Ptr();
509+
ret->RightLabel = Build<TCoAtomList>(ctx, pos)
510+
.Add(rightLabel)
511+
.Done()
512+
.Ptr();
513+
int index = scope.size();
514+
ret->Left = BuildYtJoinTree(op->LeftArg, scope, ctx, pos);
515+
ret->Right = BuildYtJoinTree(op->RightArg, scope, ctx, pos);
516+
ret->Scope.insert(ret->Scope.end(), scope.begin() + index, scope.end());
517+
return ret;
518+
} else {
519+
YQL_ENSURE(false, "Unknown node type");
520+
}
521+
}
522+
501523
} // namespace
502524

525+
bool AreSimilarTrees(TYtJoinNode::TPtr node1, TYtJoinNode::TPtr node2) {
526+
if (node1 == node2) {
527+
return true;
528+
}
529+
if (node1 && !node2) {
530+
return false;
531+
}
532+
if (node2 && !node1) {
533+
return false;
534+
}
535+
if (node1->Scope != node2->Scope) {
536+
return false;
537+
}
538+
auto opLeft = dynamic_cast<TYtJoinNodeOp*>(node1.Get());
539+
auto opRight = dynamic_cast<TYtJoinNodeOp*>(node2.Get());
540+
if (opLeft && opRight) {
541+
return AreSimilarTrees(opLeft->Left, opRight->Left)
542+
&& AreSimilarTrees(opLeft->Right, opRight->Right);
543+
} else if (!opLeft && !opRight) {
544+
return true;
545+
} else {
546+
return false;
547+
}
548+
}
549+
503550
void BuildOptimizerJoinTree(std::shared_ptr<IBaseOptimizerNode>& tree, std::shared_ptr<IProviderContext>& ctx, TYtJoinNodeOp::TPtr op)
504551
{
505552
TOptimizerTreeBuilder(tree, ctx, op).Do();
506553
}
507554

555+
TYtJoinNode::TPtr BuildYtJoinTree(std::shared_ptr<IBaseOptimizerNode> node, TExprContext& ctx, TPositionHandle pos) {
556+
TVector<TString> scope;
557+
return BuildYtJoinTree(node, scope, ctx, pos);
558+
}
559+
508560
TYtJoinNodeOp::TPtr OrderJoins(TYtJoinNodeOp::TPtr op, const TYtState::TPtr& state, TExprContext& ctx, bool debug)
509561
{
510562
if (state->Types->CostBasedOptimizer == ECostBasedOptimizerType::Disable) {

0 commit comments

Comments
 (0)