Skip to content

Commit 8859610

Browse files
committed
don't remove DESC sorting for sys view reads
1 parent fe21f71 commit 8859610

File tree

2 files changed

+233
-0
lines changed

2 files changed

+233
-0
lines changed

ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ TExprBase KqpRemoveRedundantSortOverReadTable(TExprBase node, TExprContext& ctx,
9393
}
9494

9595
if (direction == ESortDirection::Reverse) {
96+
// For sys views, we need to set reverse flag even if UseSource returns false
97+
// because sys view actors can handle reverse direction
98+
bool isSysView = tableDesc.Metadata->Kind == EKikimrTableKind::SysView;
99+
if (isSysView) {
100+
return node;
101+
}
102+
96103
if (!UseSource(kqpCtx, tableDesc) && kqpCtx.IsScanQuery()) {
97104
return node;
98105
}
@@ -206,6 +213,13 @@ TExprBase KqpRemoveRedundantSortOverReadTableFSM(
206213
}
207214

208215
if (isReversed) {
216+
// For sys views, we need to set reverse flag even if UseSource returns false
217+
// because sys view actors can handle reverse direction
218+
bool isSysView = tableDesc.Metadata->Kind == EKikimrTableKind::SysView;
219+
if (isSysView) {
220+
return node;
221+
}
222+
209223
if (!UseSource(kqpCtx, tableDesc) && kqpCtx.IsScanQuery()) {
210224
return node;
211225
}

ydb/core/kqp/ut/sysview/kqp_sys_view_ut.cpp

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,225 @@ order by SessionId;)", "%Y-%m-%d %H:%M:%S %Z", sessionsSet.front().GetId().data(
612612
UNIT_ASSERT_VALUES_EQUAL(nodeIds[4], offset);
613613
}
614614

615+
Y_UNIT_TEST(PartitionStatsOrderByDesc) {
616+
// Test ORDER BY DESC for partition_stats sys view
617+
TKikimrRunner kikimr;
618+
auto client = kikimr.GetQueryClient();
619+
auto session = client.GetSession().GetValueSync().GetSession();
620+
621+
const auto describeResult = kikimr.GetTestClient().Describe(
622+
kikimr.GetTestServer().GetRuntime(), "/Root/EightShard");
623+
624+
auto result = session.ExecuteQuery(R"(--!syntax_v1
625+
SELECT PathId, PartIdx, Path
626+
FROM `/Root/.sys/partition_stats`
627+
ORDER BY PathId DESC, PartIdx DESC
628+
)", NYdb::NQuery::TTxControl::NoTx()).GetValueSync();
629+
630+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
631+
632+
// Collect all results
633+
TVector<std::pair<ui64, ui64>> pathIdPartIdx;
634+
auto resultSet = result.GetResultSet(0);
635+
NYdb::TResultSetParser parser(resultSet);
636+
while (parser.TryNextRow()) {
637+
auto pathId = parser.ColumnParser("PathId").GetOptionalUint64().value();
638+
auto partIdx = parser.ColumnParser("PartIdx").GetOptionalUint64().value();
639+
pathIdPartIdx.push_back({pathId, partIdx});
640+
}
641+
642+
// Verify we got some results
643+
UNIT_ASSERT_C(pathIdPartIdx.size() > 0, "Expected at least one partition");
644+
645+
// Verify results are in descending order by PathId, then PartIdx
646+
for (size_t i = 1; i < pathIdPartIdx.size(); ++i) {
647+
const auto& prev = pathIdPartIdx[i - 1];
648+
const auto& curr = pathIdPartIdx[i];
649+
650+
bool isOrdered = (prev.first > curr.first) ||
651+
(prev.first == curr.first && prev.second >= curr.second);
652+
653+
UNIT_ASSERT_C(isOrdered,
654+
TStringBuilder() << "Results not in descending order: "
655+
<< "pathIdPartIdx[" << (i - 1) << "] = (" << prev.first << ", " << prev.second << ")"
656+
<< " > pathIdPartIdx[" << i << "] = (" << curr.first << ", " << curr.second << ")"
657+
<< ". ORDER BY DESC is being ignored by sys view actors.");
658+
}
659+
}
660+
661+
Y_UNIT_TEST(QuerySessionsOrderByDesc) {
662+
// Test ORDER BY DESC for query_sessions sys view
663+
NKikimrConfig::TFeatureFlags featureFlags;
664+
featureFlags.SetEnableRealSystemViewPaths(true);
665+
TKikimrSettings settings;
666+
settings.SetWithSampleTables(false);
667+
settings.SetFeatureFlags(featureFlags);
668+
settings.SetAuthToken("root@builtin");
669+
TKikimrRunner kikimr(settings);
670+
671+
auto client = kikimr.GetQueryClient();
672+
auto session = client.GetSession().GetValueSync().GetSession();
673+
674+
// Create some sessions to have data
675+
const size_t sessionsCount = 5;
676+
std::vector<NYdb::NQuery::TSession> sessionsSet;
677+
for(ui32 i = 0; i < sessionsCount; i++) {
678+
sessionsSet.emplace_back(std::move(client.GetSession().GetValueSync().GetSession()));
679+
}
680+
681+
// Wait a bit for sessions to be registered
682+
::Sleep(TDuration::MilliSeconds(100));
683+
684+
auto result = session.ExecuteQuery(R"(--!syntax_v1
685+
SELECT SessionId, State, NodeId
686+
FROM `/Root/.sys/query_sessions`
687+
ORDER BY SessionId DESC
688+
)", NYdb::NQuery::TTxControl::NoTx()).GetValueSync();
689+
690+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
691+
692+
// Collect all results
693+
TVector<std::string> sessionIds;
694+
auto resultSet = result.GetResultSet(0);
695+
NYdb::TResultSetParser parser(resultSet);
696+
while (parser.TryNextRow()) {
697+
auto sessionId = parser.ColumnParser("SessionId").GetOptionalUtf8().value();
698+
sessionIds.push_back(sessionId);
699+
}
700+
701+
// Verify we got some results
702+
UNIT_ASSERT_C(sessionIds.size() > 0, "Expected at least one session");
703+
704+
// Verify results are in descending order (lexicographically)
705+
for (size_t i = 1; i < sessionIds.size(); ++i) {
706+
UNIT_ASSERT_C(sessionIds[i - 1] >= sessionIds[i],
707+
TStringBuilder() << "Results not in descending order: "
708+
<< "sessionIds[" << (i - 1) << "] = \"" << sessionIds[i - 1] << "\""
709+
<< " < sessionIds[" << i << "] = \"" << sessionIds[i] << "\""
710+
<< ". ORDER BY DESC is being ignored by sys view actors.");
711+
}
712+
}
713+
714+
Y_UNIT_TEST(CompileCacheQueriesOrderByDesc) {
715+
// Test ORDER BY DESC for compile_cache_queries sys view
716+
auto serverSettings = TKikimrSettings().SetKqpSettings({ NKikimrKqp::TKqpSetting() });
717+
serverSettings.AppConfig.MutableTableServiceConfig()->SetEnableImplicitQueryParameterTypes(true);
718+
TKikimrRunner kikimr(serverSettings);
719+
kikimr.GetTestServer().GetRuntime()->GetAppData().FeatureFlags.SetEnableCompileCacheView(true);
720+
auto client = kikimr.GetQueryClient();
721+
auto session = client.GetSession().GetValueSync().GetSession();
722+
723+
// Execute some queries to populate compile cache
724+
auto tableClient = kikimr.GetTableClient();
725+
for (ui32 i = 0; i < 3; ++i) {
726+
auto tableSession = tableClient.CreateSession().GetValueSync().GetSession();
727+
auto paramsBuilder = TParamsBuilder();
728+
paramsBuilder.AddParam("$k").Uint64(i).Build();
729+
auto executedResult = tableSession.ExecuteDataQuery(
730+
R"(DECLARE $k AS Uint64;
731+
SELECT COUNT(*) FROM `/Root/EightShard` WHERE Key = $k;)",
732+
TTxControl::BeginTx().CommitTx(),
733+
paramsBuilder.Build()
734+
).GetValueSync();
735+
UNIT_ASSERT_C(executedResult.IsSuccess(), executedResult.GetIssues().ToString());
736+
}
737+
738+
// Wait a bit for compile cache to be updated
739+
::Sleep(TDuration::MilliSeconds(100));
740+
741+
auto result = session.ExecuteQuery(R"(--!syntax_v1
742+
SELECT QueryText, CompilationDuration
743+
FROM `/Root/.sys/compile_cache_queries`
744+
ORDER BY QueryText DESC
745+
)", NYdb::NQuery::TTxControl::NoTx()).GetValueSync();
746+
747+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
748+
749+
// Collect all results
750+
TVector<std::string> queryTexts;
751+
auto resultSet = result.GetResultSet(0);
752+
NYdb::TResultSetParser parser(resultSet);
753+
while (parser.TryNextRow()) {
754+
auto queryText = parser.ColumnParser("QueryText").GetOptionalUtf8().value();
755+
queryTexts.push_back(queryText);
756+
}
757+
758+
// Verify we got some results
759+
if (queryTexts.size() > 0) {
760+
// Verify results are in descending order (lexicographically)
761+
for (size_t i = 1; i < queryTexts.size(); ++i) {
762+
UNIT_ASSERT_C(queryTexts[i - 1] >= queryTexts[i],
763+
TStringBuilder() << "Results not in descending order: "
764+
<< "queryTexts[" << (i - 1) << "] = \"" << queryTexts[i - 1] << "\""
765+
<< " < queryTexts[" << i << "] = \"" << queryTexts[i] << "\""
766+
<< ". ORDER BY DESC is being ignored by sys view actors.");
767+
}
768+
}
769+
}
770+
771+
Y_UNIT_TEST(TopQueriesOrderByDesc) {
772+
// Test ORDER BY DESC for top_queries sys views
773+
TKikimrRunner kikimr("", KikimrDefaultUtDomainRoot, 3);
774+
auto client = kikimr.GetQueryClient();
775+
auto session = client.GetSession().GetValueSync().GetSession();
776+
777+
// Execute some queries to populate stats
778+
auto tableClient = kikimr.GetTableClient();
779+
auto tableSession = tableClient.CreateSession().GetValueSync().GetSession();
780+
{
781+
auto result = tableSession.ExecuteDataQuery(Q_(R"(
782+
SELECT * FROM `/Root/TwoShard`
783+
)"), TTxControl::BeginTx().CommitTx()).GetValueSync();
784+
UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS);
785+
}
786+
{
787+
auto result = tableSession.ExecuteDataQuery(Q_(R"(
788+
SELECT * FROM `/Root/EightShard`
789+
)"), TTxControl::BeginTx().CommitTx()).GetValueSync();
790+
UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS);
791+
}
792+
793+
// Wait a bit for stats to be collected
794+
::Sleep(TDuration::MilliSeconds(500));
795+
796+
// Test top_queries_by_read_bytes_one_minute
797+
auto result = session.ExecuteQuery(R"(--!syntax_v1
798+
SELECT IntervalEnd, Rank, ReadBytes
799+
FROM `/Root/.sys/top_queries_by_read_bytes_one_minute`
800+
ORDER BY IntervalEnd DESC, Rank DESC
801+
)", NYdb::NQuery::TTxControl::NoTx()).GetValueSync();
802+
803+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
804+
805+
// Collect all results
806+
TVector<std::pair<TInstant, ui32>> intervalEndRank;
807+
auto resultSet = result.GetResultSet(0);
808+
NYdb::TResultSetParser parser(resultSet);
809+
while (parser.TryNextRow()) {
810+
auto intervalEnd = parser.ColumnParser("IntervalEnd").GetOptionalTimestamp().value();
811+
auto rank = parser.ColumnParser("Rank").GetOptionalUint32().value();
812+
intervalEndRank.push_back({intervalEnd, rank});
813+
}
814+
815+
// Verify we got some results (may be empty if no stats collected yet)
816+
if (intervalEndRank.size() > 0) {
817+
// Verify results are in descending order by IntervalEnd, then Rank
818+
for (size_t i = 1; i < intervalEndRank.size(); ++i) {
819+
const auto& prev = intervalEndRank[i - 1];
820+
const auto& curr = intervalEndRank[i];
821+
822+
bool isOrdered = (prev.first > curr.first) ||
823+
(prev.first == curr.first && prev.second >= curr.second);
824+
825+
UNIT_ASSERT_C(isOrdered,
826+
TStringBuilder() << "Results not in descending order: "
827+
<< "intervalEndRank[" << (i - 1) << "] = (" << prev.first.ToString() << ", " << prev.second << ")"
828+
<< " > intervalEndRank[" << i << "] = (" << curr.first.ToString() << ", " << curr.second << ")"
829+
<< ". ORDER BY DESC is being ignored by sys view actors.");
830+
}
831+
}
832+
}
833+
615834
Y_UNIT_TEST(QueryStatsSimple) {
616835
auto checkTable = [&] (const TStringBuf tableName) {
617836
TKikimrRunner kikimr("", KikimrDefaultUtDomainRoot, 3);

0 commit comments

Comments
 (0)