14
14
#include < ydb-cpp-sdk/client/table/table.h>
15
15
#include < ydb/public/lib/ydb_cli/common/pretty_table.h>
16
16
#include < ydb/public/lib/yson_value/ydb_yson_value.h>
17
+ #include < ydb/public/lib/ydb_cli/common/formats.h>
18
+ #include < ydb/public/lib/ydb_cli/common/format.h>
19
+ #include < ydb/public/lib/ydb_cli/common/plan2svg.h>
20
+ #include < ydb/public/lib/ydb_cli/common/progress_indication.h>
21
+ #include < ydb-cpp-sdk/client/proto/accessor.h>
17
22
18
23
#include < ydb/public/api/protos/ydb_query.pb.h>
19
24
#include < yql/essentials/public/decimal/yql_decimal.h>
@@ -179,9 +184,21 @@ class TQueryResultScanner {
179
184
}
180
185
181
186
template <typename TIterator>
182
- bool Scan (TIterator& it) {
187
+ bool Scan (TIterator& it, std::optional<TString> planFileName = std::nullopt) {
188
+
189
+ TProgressIndication progressIndication (true );
190
+ TMaybe<NQuery::TExecStats> execStats;
191
+
192
+ TString currentPlanFileNameStats;
193
+ TString currentPlanWithStatsFileName;
194
+ TString currentPlanWithStatsFileNameJson;
195
+ if (planFileName) {
196
+ currentPlanFileNameStats = TStringBuilder () << *planFileName << " .stats" ;
197
+ currentPlanWithStatsFileName = TStringBuilder () << *planFileName << " .svg" ;
198
+ currentPlanWithStatsFileNameJson = TStringBuilder () << *planFileName << " .json" ;
199
+ }
183
200
for (;;) {
184
- auto streamPart = it.ReadNext ().GetValueSync ();
201
+ auto streamPart = it.ReadNext ().ExtractValueSync ();
185
202
ui64 rsIndex = 0 ;
186
203
187
204
if constexpr (std::is_same_v<TIterator, NTable::TScanQueryPartIterator>) {
@@ -191,13 +208,47 @@ class TQueryResultScanner {
191
208
PlanAst = streamPart.GetQueryStats ().GetAst ().value_or (" " );
192
209
}
193
210
} else {
194
- const auto & stats = streamPart.GetStats ();
195
- rsIndex = streamPart.GetResultSetIndex ();
196
- if (stats) {
197
- ServerTiming += stats->GetTotalDuration ();
198
- QueryPlan = stats->GetPlan ().value_or (" " );
199
- PlanAst = stats->GetAst ().value_or (" " );
211
+ if (streamPart.HasStats ()) {
212
+ execStats = streamPart.ExtractStats ();
213
+
214
+ if (planFileName) {
215
+ TFileOutput out (currentPlanFileNameStats);
216
+ out << execStats->ToString ();
217
+ {
218
+ auto plan = execStats->GetPlan ();
219
+ if (plan) {
220
+ {
221
+ TPlanVisualizer pv;
222
+ TFileOutput out (currentPlanWithStatsFileName);
223
+ try {
224
+ pv.LoadPlans (*execStats->GetPlan ());
225
+ out << pv.PrintSvg ();
226
+ } catch (std::exception & e) {
227
+ out << " <svg width='1024' height='256' xmlns='http://www.w3.org/2000/svg'><text>" << e.what () << " <text></svg>" ;
228
+ }
229
+ }
230
+ {
231
+ TFileOutput out (currentPlanWithStatsFileNameJson);
232
+ TQueryPlanPrinter queryPlanPrinter (EDataFormat::JsonBase64, true , out, 120 );
233
+ queryPlanPrinter.Print (*execStats->GetPlan ());
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ const auto & protoStats = TProtoAccessor::GetProto (execStats.GetRef ());
240
+ for (const auto & queryPhase : protoStats.query_phases ()) {
241
+ for (const auto & tableAccessStats : queryPhase.table_access ()) {
242
+ progressIndication.UpdateProgress ({tableAccessStats.reads ().rows (), tableAccessStats.reads ().bytes (),
243
+ tableAccessStats.updates ().rows (), tableAccessStats.updates ().bytes (),
244
+ tableAccessStats.deletes ().rows (), tableAccessStats.deletes ().bytes ()});
245
+ }
246
+ }
247
+
248
+ progressIndication.Render ();
200
249
}
250
+
251
+ rsIndex = streamPart.GetResultSetIndex ();
201
252
}
202
253
203
254
if (!streamPart.IsSuccess ()) {
@@ -212,6 +263,11 @@ class TQueryResultScanner {
212
263
RawResults[rsIndex].emplace_back (streamPart.ExtractResultSet ());
213
264
}
214
265
}
266
+ if (execStats) {
267
+ ServerTiming += execStats->GetTotalDuration ();
268
+ QueryPlan = execStats->GetPlan ().value_or (" " );
269
+ PlanAst = execStats->GetAst ().value_or (" " );
270
+ }
215
271
return true ;
216
272
}
217
273
};
@@ -255,32 +311,35 @@ TQueryBenchmarkResult ExecuteImpl(const TString& query, NTable::TTableClient& cl
255
311
}
256
312
}
257
313
258
- TQueryBenchmarkResult Execute (const TString& query, NTable::TTableClient& client, const TQueryBenchmarkDeadline& deadline ) {
259
- return ExecuteImpl (query, client, deadline , false );
314
+ TQueryBenchmarkResult Execute (const TString& query, NTable::TTableClient& client, const TQueryBenchmarkSettings& settings ) {
315
+ return ExecuteImpl (query, client, settings. Deadline , false );
260
316
}
261
317
262
318
TQueryBenchmarkResult Explain (const TString& query, NTable::TTableClient& client, const TQueryBenchmarkDeadline& deadline) {
263
319
return ExecuteImpl (query, client, deadline, true );
264
320
}
265
321
266
- TQueryBenchmarkResult ExecuteImpl (const TString& query, NQuery::TQueryClient& client, const TQueryBenchmarkDeadline& deadline , bool explainOnly) {
322
+ TQueryBenchmarkResult ExecuteImpl (const TString& query, NQuery::TQueryClient& client, const TQueryBenchmarkSettings& benchmarkSettings , bool explainOnly) {
267
323
NQuery::TExecuteQuerySettings settings;
268
324
settings.StatsMode (NQuery::EStatsMode::Full);
269
325
settings.ExecMode (explainOnly ? NQuery::EExecMode::Explain : NQuery::EExecMode::Execute);
270
- if (auto error = SetTimeoutSettings (settings, deadline)) {
326
+ if (benchmarkSettings.WithProgress ) {
327
+ settings.StatsCollectPeriod (std::chrono::milliseconds (3000 ));
328
+ }
329
+ if (auto error = SetTimeoutSettings (settings, benchmarkSettings.Deadline )) {
271
330
return *error;
272
331
}
273
332
auto it = client.StreamExecuteQuery (
274
333
query,
275
334
NYdb::NQuery::TTxControl::BeginTx ().CommitTx (),
276
335
settings).GetValueSync ();
277
- if (auto error = ResultByStatus (it, deadline .Name )) {
336
+ if (auto error = ResultByStatus (it, benchmarkSettings. Deadline .Name )) {
278
337
return *error;
279
338
}
280
339
281
340
TQueryResultScanner composite;
282
- composite.SetDeadlineName (deadline .Name );
283
- if (!composite.Scan (it)) {
341
+ composite.SetDeadlineName (benchmarkSettings. Deadline .Name );
342
+ if (!composite.Scan (it, benchmarkSettings. PlanFileName )) {
284
343
return TQueryBenchmarkResult::Error (
285
344
composite.GetErrorInfo (), composite.GetQueryPlan (), composite.GetPlanAst ());
286
345
} else {
@@ -293,12 +352,14 @@ TQueryBenchmarkResult ExecuteImpl(const TString& query, NQuery::TQueryClient& cl
293
352
}
294
353
}
295
354
296
- TQueryBenchmarkResult Execute (const TString& query, NQuery::TQueryClient& client, const TQueryBenchmarkDeadline& deadline ) {
297
- return ExecuteImpl (query, client, deadline , false );
355
+ TQueryBenchmarkResult Execute (const TString& query, NQuery::TQueryClient& client, const TQueryBenchmarkSettings& settings ) {
356
+ return ExecuteImpl (query, client, settings , false );
298
357
}
299
358
300
359
TQueryBenchmarkResult Explain (const TString& query, NQuery::TQueryClient& client, const TQueryBenchmarkDeadline& deadline) {
301
- return ExecuteImpl (query, client, deadline, true );
360
+ TQueryBenchmarkSettings settings;
361
+ settings.Deadline = deadline;
362
+ return ExecuteImpl (query, client, settings, true );
302
363
}
303
364
304
365
NJson::TJsonValue GetQueryLabels (ui32 queryId) {
0 commit comments