Skip to content

Commit 7807746

Browse files
authored
Add support for KqpOlapApply in explain (#18431)
1 parent c72071f commit 7807746

File tree

5 files changed

+58
-13
lines changed

5 files changed

+58
-13
lines changed

ydb/core/kqp/opt/kqp_query_plan.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,8 @@ class TxPlanSerializer {
11791179
return Sprintf(strRegexp[compSign].c_str(), attr.c_str(), value.c_str());
11801180
}
11811181
}
1182+
} else if (auto olapApply = TMaybeNode<TKqpOlapApply>(node)) {
1183+
return NPlanUtils::ExtractPredicate(olapApply.Cast().Lambda()).Body;
11821184
}
11831185

11841186
for (const auto& child: node->Children()) {

ydb/core/kqp/opt/kqp_statistics_transformer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ class TKqpOlapPredicateSelectivityComputer: public TPredicateSelectivityComputer
478478
tmpSelectivity *= Compute(andNode.Cast().Arg(i));
479479
}
480480
resSelectivity = tmpSelectivity;
481+
} else if (auto olapApply = input.Maybe<TKqpOlapApply>()) {
482+
resSelectivity = TPredicateSelectivityComputer::Compute(olapApply.Cast().Lambda().Body());
481483
} else if (auto orNode = input.Maybe<TKqpOlapOr>()) {
482484
double tmpSelectivity = 0.0;
483485
for (size_t i = 0; i < orNode.Cast().ArgCount(); i++) {

ydb/core/kqp/ut/join/kqp_join_order_ut.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,10 +476,9 @@ Y_UNIT_TEST_SUITE(OlapEstimationRowsCorrectness) {
476476
TestOlapEstimationRowsCorrectness("queries/tpch2.sql", "stats/tpch1000s.json");
477477
}
478478

479-
// FIXME: Cardinality estimation is broken because of new type of OLAP pushdown
480-
// Y_UNIT_TEST(TPCH3) {
481-
// TestOlapEstimationRowsCorrectness("queries/tpch3.sql", "stats/tpch1000s.json");
482-
// }
479+
Y_UNIT_TEST(TPCH3) {
480+
TestOlapEstimationRowsCorrectness("queries/tpch3.sql", "stats/tpch1000s.json");
481+
}
483482

484483
Y_UNIT_TEST(TPCH5) {
485484
TestOlapEstimationRowsCorrectness("queries/tpch5.sql", "stats/tpch1000s.json");

ydb/library/yql/dq/opt/dq_opt_predicate_selectivity.cpp

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ namespace {
2424
* Check if a callable is an attribute of some table
2525
* Currently just return a boolean and cover only basic cases
2626
*/
27-
TMaybe<TCoMember> IsAttribute(const TExprBase& input) {
27+
std::optional<TString> IsAttribute(const TExprBase& input) {
2828
if (auto member = input.Maybe<TCoMember>()) {
29-
return member.Cast();
29+
return TString(member.Cast().Name());
3030
} else if (auto cast = input.Maybe<TCoSafeCast>()) {
3131
return IsAttribute(cast.Cast().Value());
3232
} else if (auto ifPresent = input.Maybe<TCoIfPresent>()) {
@@ -42,8 +42,37 @@ namespace {
4242
} else if (auto exists = input.Maybe<TCoExists>()) {
4343
auto child = TExprBase(input.Ptr()->ChildRef(0));
4444
return IsAttribute(child);
45+
} else if (auto argument = input.Maybe<TCoArgument>()) {
46+
TString argumentName = TString(argument.Cast().Name());
47+
TStringBuf olapApplyMemberPrefix = "members_";
48+
if (argumentName.StartsWith(olapApplyMemberPrefix)) {
49+
return argumentName.substr(olapApplyMemberPrefix.length(), argumentName.size() - olapApplyMemberPrefix.length());
50+
} else {
51+
return argumentName;
52+
}
4553
}
54+
return std::nullopt;
55+
}
4656

57+
TMaybe<TCoMember> IsMember(const TExprBase& input) {
58+
if (auto member = input.Maybe<TCoMember>()) {
59+
return member.Cast();
60+
} else if (auto cast = input.Maybe<TCoSafeCast>()) {
61+
return IsMember(cast.Cast().Value());
62+
} else if (auto ifPresent = input.Maybe<TCoIfPresent>()) {
63+
return IsMember(ifPresent.Cast().Optional());
64+
} else if (auto just = input.Maybe<TCoJust>()) {
65+
return IsMember(just.Cast().Input());
66+
} else if (input.Ptr()->IsCallable("PgCast")) {
67+
auto child = TExprBase(input.Ptr()->ChildRef(0));
68+
return IsMember(child);
69+
} else if (input.Ptr()->IsCallable("FromPg")) {
70+
auto child = TExprBase(input.Ptr()->ChildRef(0));
71+
return IsMember(child);
72+
} else if (auto exists = input.Maybe<TCoExists>()) {
73+
auto child = TExprBase(input.Ptr()->ChildRef(0));
74+
return IsMember(child);
75+
}
4776
return Nothing();
4877
}
4978

@@ -223,12 +252,12 @@ double NYql::NDq::TPredicateSelectivityComputer::ComputeInequalitySelectivity(co
223252
return ComputeInequalitySelectivity(right, left, GetOppositePredicateType(predicate));
224253
}
225254

226-
if (auto maybeMember = IsAttribute(left)) {
255+
if (auto attribute = IsAttribute(left)) {
227256
// It seems like this is not possible in current version.
228257
if (IsAttribute(right)) {
229258
return 0.3;
230259
} else if (IsConstantExprWithParams(right.Ptr())) {
231-
const TString attributeName = maybeMember.Get()->Name().StringValue();
260+
const TString attributeName = attribute.value();
232261
if (!IsConstantExpr(right.Ptr())) {
233262
return DefaultSelectivity(Stats, attributeName);
234263
}
@@ -259,26 +288,32 @@ double NYql::NDq::TPredicateSelectivityComputer::ComputeEqualitySelectivity(cons
259288
return ComputeEqualitySelectivity(right, left);
260289
}
261290

262-
if (auto maybeMember = IsAttribute(left)) {
291+
if (auto attribute = IsAttribute(left)) {
263292
// In case both arguments refer to an attribute, return 0.2
264-
if (auto maybeAnotherMember = IsAttribute(right)) {
293+
if (IsAttribute(right)) {
265294
if (CollectMemberEqualities) {
266-
MemberEqualities.Add(*maybeMember.Get(), *maybeAnotherMember.Get());
295+
auto maybeMember = IsMember(left);
296+
auto maybeAnotherMember = IsMember(right);
297+
if (maybeMember && maybeAnotherMember) {
298+
MemberEqualities.Add(*maybeMember.Get(), *maybeAnotherMember.Get());
299+
}
267300
}
268301
return 0.3;
269302
}
270303
// In case the right side is a constant that can be extracted, compute the selectivity using statistics
271304
// Currently, with the basic statistics we just return 1/nRows
272305

273306
else if (IsConstantExprWithParams(right.Ptr())) {
274-
TString attributeName = maybeMember.Get()->Name().StringValue();
307+
TString attributeName = attribute.value();
275308
if (!IsConstantExpr(right.Ptr())) {
276309
return DefaultSelectivity(Stats, attributeName);
277310
}
278311

279312
if (Stats == nullptr || Stats->ColumnStatistics == nullptr) {
280313
if (CollectColumnsStatUsedMembers) {
281-
ColumnStatsUsedMembers.AddEquality(*maybeMember.Get());
314+
if (auto maybeMember = IsMember(left)) {
315+
ColumnStatsUsedMembers.AddEquality(*maybeMember.Get());
316+
}
282317
}
283318
return DefaultSelectivity(Stats, attributeName);
284319
}

ydb/library/yql/utils/plan/plan_utils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ TString PrettyExprStr(const TExprBase& expr) {
285285

286286
return TStringBuilder() << "[" << JoinStrings(std::move(items), ",") << "]";
287287
} else {
288+
if (auto arg = expr.Maybe<TCoArgument>()) {
289+
TStringBuf yqlOlapApplyMember = "members_";
290+
TString argumentName = TString(arg.Cast().Name());
291+
if (argumentName.StartsWith(yqlOlapApplyMember)) {
292+
return argumentName.substr(yqlOlapApplyMember.length(), argumentName.length() - yqlOlapApplyMember.length());
293+
}
294+
}
288295
auto raw = TString(expr.Ref().Content());
289296
// return raw.StartsWith("_yql_agg_") ? "" : raw;
290297
return raw;

0 commit comments

Comments
 (0)