Skip to content

Commit bb31075

Browse files
committed
Remove reads duplication
1 parent 80c6a49 commit bb31075

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

ydb/core/kqp/opt/kqp_opt_build_txs.cpp

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ class TKqpBuildTxsTransformer : public TSyncTransformerBase {
771771

772772
TNodeOnNodeOwnedMap phaseStagesMap;
773773
TVector<TKqlQueryResult> phaseResults;
774-
TVector<TDqPhyPrecompute> computedInputs;
774+
TVector<TExprBase> computedInputs;
775775
TNodeSet computedInputsSet;
776776

777777
// Gather all Precompute stages, that are independent of any other stage and form phase of execution
@@ -785,12 +785,92 @@ class TKqpBuildTxsTransformer : public TSyncTransformerBase {
785785
phaseStagesMap.emplace(raw, ptr);
786786
}
787787

788+
{
789+
TNodeOnNodeOwnedMap fullPhaseStagesMap;
790+
for (auto& [_, stagePtr] : phaseStagesMap) {
791+
VisitExpr(stagePtr,
792+
[&](const TExprNode::TPtr& node) {
793+
if (TExprBase(node).Maybe<TDqStage>()) {
794+
fullPhaseStagesMap[node.Get()] = node;
795+
}
796+
return true;
797+
});
798+
}
799+
phaseStagesMap.swap(fullPhaseStagesMap);
800+
801+
TNodeOnNodeOwnedMap fullDependantMap;
802+
VisitExpr(query.Ptr(),
803+
[&](const TExprNode::TPtr& node) {
804+
if (phaseStagesMap.contains(node.Get())) {
805+
return false;
806+
}
807+
if (TExprBase(node).Maybe<TDqStage>()) {
808+
fullDependantMap[node.Get()] = node;
809+
}
810+
return true;
811+
});
812+
dependantStagesMap.swap(fullDependantMap);
813+
}
814+
788815
if (phaseStagesMap.empty()) {
789816
output = query.Ptr();
790817
ctx.AddError(TIssue(ctx.GetPosition(query.Pos()), "Phase stages is empty"));
791818
return TStatus::Error;
792819
}
793820

821+
// so that all outputs to dependent stages are precomputes
822+
{
823+
TSet<TExprNode*> buildingTxStages;
824+
825+
TNodeOnNodeOwnedMap replaces;
826+
827+
for (auto& [_, stagePtr] : dependantStagesMap) {
828+
TDqStage stage(stagePtr);
829+
for (size_t i = 0; i < stage.Inputs().Size(); ++i) {
830+
auto input = stage.Inputs().Item(i);
831+
if (auto maybeConn = input.Maybe<TDqConnection>()) {
832+
auto conn = maybeConn.Cast();
833+
if (phaseStagesMap.contains(conn.Output().Stage().Raw())) {
834+
auto oldArg = stage.Program().Args().Arg(i);
835+
auto newArg = Build<TCoArgument>(ctx, stage.Program().Args().Arg(i).Pos())
836+
.Name("_replaced_arg")
837+
.Done();
838+
839+
TVector<TCoArgument> newArgs;
840+
TNodeOnNodeOwnedMap programReplaces;
841+
for (size_t j = 0; j < stage.Program().Args().Size(); ++j) {
842+
auto oldArg = stage.Program().Args().Arg(j);
843+
newArgs.push_back(Build<TCoArgument>(ctx, stage.Program().Args().Arg(i).Pos())
844+
.Name("_replaced_arg_" + ToString(j))
845+
.Done());
846+
if (i == j) {
847+
programReplaces[oldArg.Raw()] = Build<TCoToFlow>(ctx, oldArg.Pos()).Input(newArgs.back()).Done().Ptr();
848+
} else {
849+
programReplaces[oldArg.Raw()] = newArgs.back().Ptr();
850+
}
851+
}
852+
853+
replaces[stage.Raw()] =
854+
Build<TDqStage>(ctx, stage.Pos())
855+
.Inputs(ctx.ReplaceNode(stage.Inputs().Ptr(), input.Ref(), Build<TDqPhyPrecompute>(ctx, input.Pos()).Connection(conn).Done().Ptr()))
856+
.Outputs(stage.Outputs())
857+
.Settings(stage.Settings())
858+
.Program()
859+
.Args(newArgs)
860+
.Body(TExprBase(ctx.ReplaceNodes(stage.Program().Body().Ptr(), programReplaces)))
861+
.Build()
862+
.Done().Ptr();
863+
}
864+
}
865+
}
866+
}
867+
868+
if (!replaces.empty()) {
869+
output = ctx.ReplaceNodes(query.Ptr(), replaces);
870+
return TStatus(TStatus::Repeat, true);
871+
}
872+
}
873+
794874
for (auto& [_, stagePtr] : dependantStagesMap) {
795875
TDqStage stage(stagePtr);
796876
auto precomputes = PrecomputeInputs(stage);

ydb/core/kqp/ut/opt/kqp_returning_ut.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,25 @@ Y_UNIT_TEST(ReturningTwice) {
9696
.AddParam("$limit").Int32(1).Build()
9797
.Build();
9898

99-
auto result = session.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx(), params).GetValueSync();
99+
NYdb::NTable::TExecDataQuerySettings execSettings;
100+
execSettings.CollectQueryStats(ECollectQueryStatsMode::Full);
101+
102+
auto result = session.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx(), params, execSettings).GetValueSync();
100103
UNIT_ASSERT(result.IsSuccess());
101104

102-
//CompareYson(R"([[1]])", FormatResultSetYson(result.GetResultSet(0)));
105+
size_t eta_table_access = 0;
106+
auto stats = NYdb::TProtoAccessor::GetProto(*result.GetStats());
107+
108+
for (auto phase : stats.query_phases()) {
109+
for (auto table : phase.table_access()) {
110+
if (table.name() == "/Root/tasks_eta_002") {
111+
eta_table_access++;
112+
}
113+
}
114+
}
115+
Cerr << "access count " << eta_table_access << Endl;
116+
UNIT_ASSERT_EQUAL(eta_table_access, 1);
117+
//Cerr << stats.Utf8DebugString() << Endl;
103118
}
104119
}
105120

0 commit comments

Comments
 (0)