aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgvit <gvit@ydb.tech>2022-10-19 13:54:23 +0300
committergvit <gvit@ydb.tech>2022-10-19 13:54:23 +0300
commit2dbcdae6cc17c38d4ffed47ac9dcab10be6de9d2 (patch)
treedc2c622ff725760e8a76bbc6668b994bffb68eb7
parent741e5f61cf7dcc3f87d87ed03a6b7ee7508cf857 (diff)
downloadydb-2dbcdae6cc17c38d4ffed47ac9dcab10be6de9d2.tar.gz
PR from branch users/gvit/refactor-clickbench
-rw-r--r--ydb/public/lib/ydb_cli/commands/CMakeLists.txt44
-rw-r--r--ydb/public/lib/ydb_cli/commands/click_bench.cpp357
-rw-r--r--ydb/public/lib/ydb_cli/commands/click_bench.h137
-rw-r--r--ydb/public/lib/ydb_cli/commands/click_bench_queries.sql172
-rw-r--r--ydb/public/lib/ydb_cli/commands/click_bench_schema.sql112
-rw-r--r--ydb/public/lib/ydb_cli/commands/stock_workload.h2
-rw-r--r--ydb/public/lib/ydb_cli/commands/ydb_workload.cpp2
7 files changed, 825 insertions, 1 deletions
diff --git a/ydb/public/lib/ydb_cli/commands/CMakeLists.txt b/ydb/public/lib/ydb_cli/commands/CMakeLists.txt
index b8b2152f9e4..01ecb9370cc 100644
--- a/ydb/public/lib/ydb_cli/commands/CMakeLists.txt
+++ b/ydb/public/lib/ydb_cli/commands/CMakeLists.txt
@@ -34,8 +34,10 @@ target_link_libraries(clicommands PUBLIC
cpp-client-ydb_table
cpp-client-ydb_topic
ydb_types-credentials-login
+ library-cpp-resource
)
target_sources(clicommands PRIVATE
+ ${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/click_bench.cpp
${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/stock_workload.cpp
${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/kv_workload.cpp
${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/ydb_sdk_core_access.cpp
@@ -56,3 +58,45 @@ target_sources(clicommands PRIVATE
${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/ydb_workload.cpp
${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/ydb_yql.cpp
)
+
+add_global_library_for(clicommands.global clicommands)
+target_link_libraries(clicommands.global PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+ cpp-histogram-hdr
+ cpp-protobuf-json
+ cpp-regex-pcre
+ cpp-threading-local_executor
+ kikimr_backup
+ ydb-library-workload
+ public-lib-operation_id
+ common
+ lib-ydb_cli-dump
+ lib-ydb_cli-import
+ topic
+ cpp-client-draft
+ cpp-client-ydb_discovery
+ cpp-client-ydb_export
+ cpp-client-ydb_import
+ cpp-client-ydb_monitoring
+ cpp-client-ydb_operation
+ cpp-client-ydb_persqueue_public
+ cpp-client-ydb_proto
+ cpp-client-ydb_scheme
+ cpp-client-ydb_table
+ cpp-client-ydb_topic
+ ydb_types-credentials-login
+ library-cpp-resource
+)
+target_sources(clicommands.global PRIVATE
+ ${CMAKE_BINARY_DIR}/ydb/public/lib/ydb_cli/commands/b27fa204a2892655fc6f34eb84a6343b.cpp
+)
+resources(clicommands.global
+ ${CMAKE_BINARY_DIR}/ydb/public/lib/ydb_cli/commands/b27fa204a2892655fc6f34eb84a6343b.cpp
+ INPUTS
+ ${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/click_bench_queries.sql
+ ${CMAKE_SOURCE_DIR}/ydb/public/lib/ydb_cli/commands/click_bench_schema.sql
+ KEYS
+ click_bench_queries.sql
+ click_bench_schema.sql
+)
diff --git a/ydb/public/lib/ydb_cli/commands/click_bench.cpp b/ydb/public/lib/ydb_cli/commands/click_bench.cpp
new file mode 100644
index 00000000000..9d76e89b7c6
--- /dev/null
+++ b/ydb/public/lib/ydb_cli/commands/click_bench.cpp
@@ -0,0 +1,357 @@
+#include <util/string/split.h>
+#include <util/stream/file.h>
+#include <util/string/strip.h>
+#include <util/string/printf.h>
+#include <util/folder/pathsplit.h>
+#include <library/cpp/json/json_writer.h>
+
+#include <library/cpp/http/simple/http_client.h>
+#include <library/cpp/string_utils/base64/base64.h>
+
+#include "click_bench.h"
+
+using namespace NYdb;
+using namespace NYdb::NTable;
+
+
+static void ThrowOnError(const TStatus& status) {
+ if (!status.IsSuccess()) {
+ ythrow yexception() << "Operation failed with status " << status.GetStatus() << ": "
+ << status.GetIssues().ToString();
+ }
+}
+
+static NJson::TJsonValue GetQueryLabels(ui32 queryId) {
+ NJson::TJsonValue labels(NJson::JSON_MAP);
+ labels.InsertValue("query", Sprintf("Query%02u", queryId));
+ return labels;
+}
+
+static NJson::TJsonValue GetSensorValue(TStringBuf sensor, TDuration& value, ui32 queryId) {
+ NJson::TJsonValue sensorValue(NJson::JSON_MAP);
+ sensorValue.InsertValue("sensor", sensor);
+ sensorValue.InsertValue("value", value.MilliSeconds());
+ sensorValue.InsertValue("labels", GetQueryLabels(queryId));
+ return sensorValue;
+}
+
+static NJson::TJsonValue GetSensorValue(TStringBuf sensor, double value, ui32 queryId) {
+ NJson::TJsonValue sensorValue(NJson::JSON_MAP);
+ sensorValue.InsertValue("sensor", sensor);
+ sensorValue.InsertValue("value", value);
+ sensorValue.InsertValue("labels", GetQueryLabels(queryId));
+ return sensorValue;
+}
+
+void TClickHouseBench::Init() {
+ TString createSql = NResource::Find("click_bench_schema.sql");
+ TTableClient client(Driver);
+
+ SubstGlobal(createSql, "{table}", FullTablePath());
+ ThrowOnError(client.RetryOperationSync([createSql](TSession session) {
+ return session.ExecuteSchemeQuery(createSql).GetValueSync();
+ }));
+}
+
+
+TClickHouseBench::TTestInfo TClickHouseBench::AnalyzeTestRuns(const TVector<TDuration>& timings) {
+ TTestInfo info;
+
+ if (timings.empty()) {
+ return info;
+ }
+
+ info.ColdTime = timings[0];
+
+ if (timings.size() > 1) {
+ ui32 sum = 0;
+ for (size_t j = 1; j < timings.size(); ++j) {
+ if (info.Max < timings[j]) {
+ info.Max = timings[j];
+ }
+ if (!info.Min || info.Min > timings[j]) {
+ info.Min = timings[j];
+ }
+ sum += timings[j].MilliSeconds();
+ }
+ info.Mean = (double) sum / (double) (timings.size() - 1);
+ if (timings.size() > 2) {
+ double variance = 0;
+ for (size_t j = 1; j < timings.size(); ++j) {
+ variance += (info.Mean - timings[j].MilliSeconds()) * (info.Mean - timings[j].MilliSeconds());
+ }
+ variance = variance / (double) (timings.size() - 2);
+ info.Std = sqrt(variance);
+ }
+ }
+
+ return info;
+}
+
+TClickBenchCommandInit::TClickBenchCommandInit()
+ : TYdbCommand("init", {"i"}, "Initialize table")
+{}
+
+void TClickBenchCommandInit::Config(TConfig& config) {
+ NYdb::NConsoleClient::TClientCommand::Config(config);
+ config.SetFreeArgsNum(0);
+
+ config.Opts->AddLongOption("table", "Table name to work with")
+ .Optional()
+ .RequiredArgument("NAME")
+ .DefaultValue("hits")
+ .StoreResult(&Table);
+ config.Opts->AddLongOption('p', "path", "Relative path to table")
+ .Optional()
+ .RequiredArgument("PATH")
+ .Handler1T<TStringBuf>([this](TStringBuf arg) {
+ if (arg.StartsWith('/')) {
+ ythrow NLastGetopt::TUsageException() << "Path must be relative";
+ }
+ Path = arg;
+ });
+};
+
+int TClickBenchCommandInit::Run(TConfig& config) {
+ auto driver = CreateDriver(config);
+
+ TClickHouseBench chb(driver, config.Database, Path, Table);
+ chb.Init();
+ Cout << "Table created" << Endl;
+ driver.Stop(true);
+ return 0;
+};
+
+
+TClickBenchCommandRun::TClickBenchCommandRun()
+ : TYdbCommand("run", {"b"}, "Perform benchmark")
+{}
+
+void TClickBenchCommandRun::Config(TConfig& config) {
+ TClientCommand::Config(config);
+ config.SetFreeArgsNum(0);
+ config.Opts->AddLongOption('o', "output", "Save queries output to file")
+ .Optional()
+ .RequiredArgument("FILE")
+ .DefaultValue("results.out")
+ .StoreResult(&OutFilePath);
+ config.Opts->AddLongOption('n', "iterations", "Iterations count (without cold-start run)")
+ .DefaultValue(0)
+ .StoreResult(&IterationsCount);
+ config.Opts->AddLongOption('j', "json", "Json report file name")
+ .DefaultValue("")
+ .StoreResult(&JsonReportFileName);
+ config.Opts->AddLongOption("disable-llvm", "disable llvm")
+ .NoArgument()
+ .SetFlag(&DisableLlvm);
+ config.Opts->AddLongOption("enable-pushdown", "enabled pushdown")
+ .NoArgument()
+ .SetFlag(&EnablePushdown);
+ config.Opts->AddLongOption('f', "ext-queries-file", "File with external queries. Separated by ';'")
+ .DefaultValue("")
+ .StoreResult(&ExternalQueriesFile);
+ config.Opts->AddLongOption("table", "Table name to work with")
+ .Optional()
+ .RequiredArgument("NAME")
+ .DefaultValue("hits")
+ .StoreResult(&Table);
+ config.Opts->AddLongOption("path", "Relative path to table")
+ .Optional()
+ .RequiredArgument("PATH")
+ .Handler1T<TStringBuf>([this](TStringBuf arg) {
+ if (arg.StartsWith('/')) {
+ ythrow NLastGetopt::TUsageException() << "Path must be relative";
+ }
+ Path = arg;
+ });
+ config.Opts->AddLongOption('q', "ext-query", "String with external queries. Separated by ';'")
+ .DefaultValue("")
+ .StoreResult(&ExternalQueries);
+
+ auto fillTestCases = [](TStringBuf line, std::function<void(ui32)>&& op) {
+ for (const auto& token : StringSplitter(line).Split(',').SkipEmpty()) {
+ TStringBuf part = token.Token();
+ TStringBuf from, to;
+ if (part.TrySplit('-', from, to)) {
+ ui32 begin = FromString(from);
+ ui32 end = FromString(to);
+ while (begin <= end) {
+ op(begin);
+ ++begin;
+ }
+ } else {
+ op(FromString<ui32>(part));
+ }
+ }
+ };
+
+ auto includeOpt = config.Opts->AddLongOption("include",
+ "Run only specified queries (ex.: 1,2,3,5-10,20)")
+ .Optional()
+ .Handler1T<TStringBuf>([this, fillTestCases](TStringBuf line) {
+ QueriesToRun.clear();
+ fillTestCases(line, [this](ui32 q) {
+ QueriesToRun.insert(q);
+ });
+ });
+ auto excludeOpt = config.Opts->AddLongOption("exclude",
+ "Run all queries except given ones (ex.: 1,2,3,5-10,20)")
+ .Optional()
+ .Handler1T<TStringBuf>([this, fillTestCases](TStringBuf line) {
+ fillTestCases(line, [this](ui32 q) {
+ QueriesToSkip.emplace(q);
+ });
+ });
+
+ config.Opts->MutuallyExclusiveOpt(includeOpt, excludeOpt);
+};
+
+
+int TClickBenchCommandRun::Run(TConfig& config) {
+ auto driver = CreateDriver(config);
+ TClickHouseBench chb(driver, config.Database, Path, Table);
+ std::unique_ptr<IQueryRunner> runner;
+ runner = std::make_unique<TStreamQueryRunner>(driver);
+ const bool okay = chb.RunBench(*runner, *this);
+ driver.Stop(true);
+ return !okay;
+};
+
+
+bool TClickHouseBench::RunBench(IQueryRunner& queryRunner, const TBenchContext& context)
+{
+ TOFStream outFStream{context.OutFilePath};
+
+ TStringStream report;
+ report << "Results for " << (context.IterationsCount + 1) << " iterations" << Endl;
+ report << "+---------+----------+---------+---------+----------+---------+" << Endl;
+ report << "| Query # | ColdTime | Min | Max | Mean | Std |" << Endl;
+ report << "+---------+----------+---------+---------+----------+---------+" << Endl;
+
+ NJson::TJsonValue jsonReport(NJson::JSON_ARRAY);
+ const bool collectJsonSensors = !context.JsonReportFileName.empty();
+ const TString queries = queryRunner.GetQueries(FullTablePath(), context.GetExternalQueries());
+ i32 queryN = 0;
+ bool allOkay = true;
+ for (auto& qtoken : StringSplitter(queries).Split(';')) {
+ if (!context.NeedRun(++queryN)) {
+ continue;
+ }
+ const TString query = context.PatchQuery(qtoken.Token());
+
+ TVector<TDuration> timings;
+ timings.reserve(1 + context.IterationsCount);
+
+ Cout << Sprintf("Query%02u", queryN) << ":" << Endl;
+ Cerr << "Query text:\n" << Endl;
+ Cerr << query << Endl << Endl;
+
+ for (ui32 i = 0; i <= context.IterationsCount; ++i) {
+ auto t1 = TInstant::Now();
+ auto res = queryRunner.Execute(query);
+
+ auto duration = TInstant::Now() - t1;
+
+ Cout << "\titeration " << i << ":\t";
+ if (res.second == "") {
+ Cout << "ok\t" << duration << " seconds" << Endl;
+ timings.emplace_back(duration);
+ } else {
+ allOkay = false;
+ Cout << "failed\t" << duration << " seconds" << Endl;
+ Cerr << queryN << ": " << query << Endl
+ << res.first << res.second << Endl;
+ }
+
+ if (i == 0) {
+ outFStream << queryN << ": " << Endl
+ << res.first << res.second << Endl << Endl;
+ }
+ }
+
+ auto testInfo = AnalyzeTestRuns(timings);
+ report << Sprintf("| %02u | %8zu | %7zu | %7.zu | %8.2f | %7.2f |", queryN,
+ testInfo.ColdTime.MilliSeconds(), testInfo.Min.MilliSeconds(), testInfo.Max.MilliSeconds(),
+ testInfo.Mean, testInfo.Std) << Endl;
+ if (collectJsonSensors) {
+ jsonReport.AppendValue(GetSensorValue("ColdTime", testInfo.ColdTime, queryN));
+ jsonReport.AppendValue(GetSensorValue("Min", testInfo.Min, queryN));
+ jsonReport.AppendValue(GetSensorValue("Max", testInfo.Max, queryN));
+ jsonReport.AppendValue(GetSensorValue("Mean", testInfo.Mean, queryN));
+ jsonReport.AppendValue(GetSensorValue("Std", testInfo.Std, queryN));
+ }
+ }
+
+ report << "+---------+----------+---------+---------+----------+---------+" << Endl;
+
+ Cout << Endl << report.Str() << Endl;
+ Cout << "Results saved to " << context.OutFilePath << Endl;
+
+ if (collectJsonSensors) {
+ TOFStream jStream{context.JsonReportFileName};
+ NJson::WriteJson(&jStream, &jsonReport, /*formatOutput*/ true);
+ jStream.Finish();
+ Cout << "Report saved to " << context.JsonReportFileName << Endl;
+ }
+
+ return allOkay;
+}
+
+TString TClickHouseBench::FullTablePath() const {
+ TPathSplitUnix prefixPathSplit(Database);
+ prefixPathSplit.AppendComponent(Path);
+ prefixPathSplit.AppendComponent(Table);
+ return prefixPathSplit.Reconstruct();
+}
+
+
+TString TStreamQueryRunner::GetQueries(const TString& fullTablePath, const TString& externalQueries) {
+ TString queries = externalQueries ? externalQueries : NResource::Find("click_bench_queries.sql");
+ SubstGlobal(queries, "{table}", "`" + fullTablePath + "`");
+ return queries;
+}
+
+std::pair<TString, TString> TStreamQueryRunner::Execute(const TString& query) {
+ TStreamExecScanQuerySettings settings;
+ settings.CollectQueryStats(ECollectQueryStatsMode::Full);
+ auto it = SqClient.StreamExecuteScanQuery(query, settings).GetValueSync();
+ ThrowOnError(it);
+ return ResultToYson(it);
+}
+
+std::pair<TString, TString> TStreamQueryRunner::ResultToYson(NTable::TScanQueryPartIterator& it) {
+ TStringStream out;
+ TStringStream err_out;
+ NYson::TYsonWriter writer(&out, NYson::EYsonFormat::Text, ::NYson::EYsonType::Node, true);
+ writer.OnBeginList();
+
+ for (;;) {
+ auto streamPart = it.ReadNext().GetValueSync();
+ if (!streamPart.IsSuccess()) {
+ if (!streamPart.EOS()) {
+ err_out << streamPart.GetIssues().ToString() << Endl;
+ }
+ break;
+ }
+
+ if (streamPart.HasResultSet()) {
+ auto result = streamPart.ExtractResultSet();
+ auto columns = result.GetColumnsMeta();
+
+ NYdb::TResultSetParser parser(result);
+ while (parser.TryNextRow()) {
+ writer.OnListItem();
+ writer.OnBeginList();
+ for (ui32 i = 0; i < columns.size(); ++i) {
+ writer.OnListItem();
+ FormatValueYson(parser.GetValue(i), writer);
+ }
+ writer.OnEndList();
+ out << "\n";
+ }
+ }
+ }
+
+ writer.OnEndList();
+ return {out.Str(), err_out.Str()};
+}
diff --git a/ydb/public/lib/ydb_cli/commands/click_bench.h b/ydb/public/lib/ydb_cli/commands/click_bench.h
new file mode 100644
index 00000000000..69b28218893
--- /dev/null
+++ b/ydb/public/lib/ydb_cli/commands/click_bench.h
@@ -0,0 +1,137 @@
+#pragma once
+
+#include <ydb/public/sdk/cpp/client/ydb_table/table.h>
+#include <ydb/public/lib/yson_value/ydb_yson_value.h>
+#include <ydb/public/lib/ydb_cli/common/root.h>
+#include <util/generic/set.h>
+
+#include "ydb_command.h"
+
+struct IQueryRunner {
+ virtual ~IQueryRunner() = default;
+ virtual TString GetQueries(const TString& fullTablePath, const TString& externalQueries) = 0;
+ virtual std::pair<TString, TString> Execute(const TString& query) = 0;
+};
+
+class TBenchContext {
+protected:
+ TSet<ui32> QueriesToRun;
+ TSet<ui32> QueriesToSkip;
+ bool DisableLlvm = false;
+ bool EnablePushdown = false;
+ TString ExternalQueries;
+ TString ExternalQueriesFile;
+public:
+ TString OutFilePath;
+ ui32 IterationsCount;
+ TString JsonReportFileName;
+
+ TString GetExternalQueries() const {
+ TString externalQueries;
+ if (ExternalQueries) {
+ externalQueries = ExternalQueries;
+ } else if (ExternalQueriesFile) {
+ TFileInput fInput(ExternalQueriesFile);
+ externalQueries = fInput.ReadAll();
+ }
+ return externalQueries;
+ }
+
+ TString PatchQuery(const TStringBuf& original) const {
+ TString result(original.data(), original.size());
+ if (EnablePushdown) {
+ result = "PRAGMA ydb.KqpPushOlapProcess = \"true\";\n" + result;
+ }
+ if (DisableLlvm) {
+ result = "PRAGMA ydb.EnableLlvm=\"false\";\n" + result;
+ }
+ return result;
+ }
+
+ bool NeedRun(const ui32 queryIdx) const {
+ if (QueriesToRun.size() && !QueriesToRun.contains(queryIdx)) {
+ return false;
+ }
+ if (QueriesToSkip.contains(queryIdx)) {
+ return false;
+ }
+ return true;
+ }
+};
+
+class TClickHouseBench {
+public:
+ TClickHouseBench(NYdb::TDriver& driver, const TString& db, const TString& path, const TString& table)
+ : Driver(driver)
+ , Database(db)
+ , Path(path)
+ , Table(table)
+ {}
+
+ void Init();
+ bool RunBench(IQueryRunner& queryRunner, const TBenchContext& context);
+
+private:
+ struct TTestInfo {
+ TDuration ColdTime;
+ TDuration Min;
+ TDuration Max;
+ double Mean = 0;
+ double Std = 0;
+ };
+
+ static TTestInfo AnalyzeTestRuns(const TVector<TDuration>& timings);
+ TString FullTablePath() const;
+
+ NYdb::TDriver& Driver;
+ const TString& Database;
+ const TString& Path;
+ const TString& Table;
+};
+
+
+class TClickBenchCommandInit : public NYdb::NConsoleClient::TYdbCommand {
+public:
+ TClickBenchCommandInit();
+ void Config(TConfig& config);
+ int Run(TConfig& config);
+
+private:
+ TString Path;
+ TString Table;
+};
+
+
+class TStreamQueryRunner : public IQueryRunner {
+public:
+ explicit TStreamQueryRunner(NYdb::TDriver& driver)
+ : SqClient(driver)
+ {}
+ TString GetQueries(const TString& fullTablePath, const TString& externalQueries) override;
+ std::pair<TString, TString> Execute(const TString& query) override;
+
+private:
+ std::pair<TString, TString> ResultToYson(NYdb::NTable::TScanQueryPartIterator& it);
+
+private:
+ NYdb::NTable::TTableClient SqClient;
+};
+
+class TClickBenchCommandRun : public NYdb::NConsoleClient::TYdbCommand, public TBenchContext {
+public:
+ TClickBenchCommandRun();
+ void Config(TConfig& config);
+ int Run(TConfig& config);
+private:
+ TString Path;
+ TString Table;
+};
+
+class TCommandClickBench : public NYdb::NConsoleClient::TClientCommandTree {
+public:
+ TCommandClickBench() : TClientCommandTree("click_bench") {
+ AddCommand(std::make_unique<TClickBenchCommandRun>());
+ AddCommand(std::make_unique<TClickBenchCommandInit>());
+ }
+};
+
diff --git a/ydb/public/lib/ydb_cli/commands/click_bench_queries.sql b/ydb/public/lib/ydb_cli/commands/click_bench_queries.sql
new file mode 100644
index 00000000000..36f4aaa1518
--- /dev/null
+++ b/ydb/public/lib/ydb_cli/commands/click_bench_queries.sql
@@ -0,0 +1,172 @@
+--
+-- Basic ClickHouse performance test.
+-- Queries are adapted from https://github.com/ClickHouse/ClickHouse/blob/master/benchmark/clickhouse/queries.sql
+--
+-- NB: click_bench separates queries using simple splitting by semicolon.
+--
+
+-- q1
+SELECT count(*) FROM {table};
+-- q2
+SELECT count(*) FROM {table} WHERE AdvEngineID != 0;
+-- q3
+SELECT sum(AdvEngineID), count(*), avg(ResolutionWidth) FROM {table};
+-- q4
+SELECT sum(UserID) FROM {table};
+-- q5
+SELECT CountDistinctEstimate(UserID) FROM {table};
+-- q6
+SELECT CountDistinctEstimate(SearchPhrase) FROM {table};
+-- q7
+SELECT min(EventDate), max(EventDate) FROM {table};
+-- q8
+SELECT AdvEngineID, count(*) as c FROM {table} WHERE AdvEngineID != 0 GROUP BY AdvEngineID ORDER BY c DESC;
+-- q9
+SELECT RegionID, CountDistinctEstimate(UserID) AS u FROM {table} GROUP BY RegionID ORDER BY u DESC LIMIT 10;
+-- q10
+SELECT RegionID, sum(AdvEngineID), count(*) AS c, avg(ResolutionWidth), CountDistinctEstimate(UserID)
+FROM {table} GROUP BY RegionID ORDER BY c DESC LIMIT 10;
+-- q11
+SELECT MobilePhoneModel, CountDistinctEstimate(UserID) AS u
+FROM {table} WHERE MobilePhoneModel != '' GROUP BY MobilePhoneModel ORDER BY u DESC LIMIT 10;
+-- q12
+SELECT MobilePhone, MobilePhoneModel, CountDistinctEstimate(UserID) AS u
+FROM {table} WHERE MobilePhoneModel != '' GROUP BY MobilePhone, MobilePhoneModel ORDER BY u DESC LIMIT 10;
+-- q13
+SELECT SearchPhrase, count(*) AS c
+FROM {table} WHERE SearchPhrase != '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q14
+SELECT SearchPhrase, CountDistinctEstimate(UserID) AS u
+FROM {table} WHERE SearchPhrase != '' GROUP BY SearchPhrase ORDER BY u DESC LIMIT 10;
+-- q15
+SELECT SearchEngineID, SearchPhrase, count(*) AS c
+FROM {table} WHERE SearchPhrase != '' GROUP BY SearchEngineID, SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q16
+SELECT UserID, count(*) AS c FROM {table} GROUP BY UserID ORDER BY c DESC LIMIT 10;
+-- q17
+SELECT UserID, SearchPhrase, count(*) AS c FROM {table} GROUP BY UserID, SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q18
+SELECT UserID, SearchPhrase, count(*) AS c FROM {table} GROUP BY UserID, SearchPhrase LIMIT 10;
+-- q19
+SELECT UserID, m, SearchPhrase, count(*) AS c
+FROM {table} GROUP BY UserID, DateTime::GetMinute(EventTime) AS m, SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q20
+SELECT UserID FROM {table} WHERE UserID = 12345678901234567890;
+-- q21
+SELECT count(*) FROM {table} WHERE URL LIKE '%metrika%';
+-- q22
+SELECT SearchPhrase, some(URL), count(*) AS c
+FROM {table} WHERE URL LIKE '%metrika%' AND SearchPhrase != '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q23
+SELECT SearchPhrase, some(URL), some(Title), count(*) AS c, CountDistinctEstimate(UserID)
+FROM {table} WHERE Title LIKE '%Яндекс%' AND URL NOT LIKE '%.yandex.%' AND SearchPhrase != ''
+GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;
+-- q24
+SELECT * FROM {table} WHERE URL LIKE '%metrika%' ORDER BY EventTime LIMIT 10;
+-- q25
+SELECT SearchPhrase, EventTime FROM {table} WHERE SearchPhrase != '' ORDER BY EventTime LIMIT 10;
+-- q26
+SELECT SearchPhrase FROM {table} WHERE SearchPhrase != '' ORDER BY SearchPhrase LIMIT 10;
+-- q27
+SELECT SearchPhrase, EventTime FROM {table} WHERE SearchPhrase != '' ORDER BY EventTime, SearchPhrase LIMIT 10;
+-- q28
+SELECT CounterID, avg(length(URL)) AS l, count(*) AS c
+FROM {table} WHERE URL != '' GROUP BY CounterID HAVING count(*) > 100000 ORDER BY l DESC LIMIT 25;
+-- q29
+SELECT key, avg(length(Referer)) AS l, count(*) AS c, some(Referer)
+FROM {table} WHERE Referer != '' GROUP BY Url::CutWWW(Url::GetHost(Referer)) AS key
+HAVING count(*) > 100000 ORDER BY l DESC LIMIT 25;
+-- q30
+SELECT
+ sum(ResolutionWidth), sum(ResolutionWidth + 1), sum(ResolutionWidth + 2), sum(ResolutionWidth + 3),
+ sum(ResolutionWidth + 4), sum(ResolutionWidth + 5), sum(ResolutionWidth + 6), sum(ResolutionWidth + 7),
+ sum(ResolutionWidth + 8), sum(ResolutionWidth + 9), sum(ResolutionWidth + 10), sum(ResolutionWidth + 11),
+ sum(ResolutionWidth + 12), sum(ResolutionWidth + 13), sum(ResolutionWidth + 14), sum(ResolutionWidth + 15),
+ sum(ResolutionWidth + 16), sum(ResolutionWidth + 17), sum(ResolutionWidth + 18), sum(ResolutionWidth + 19),
+ sum(ResolutionWidth + 20), sum(ResolutionWidth + 21), sum(ResolutionWidth + 22), sum(ResolutionWidth + 23),
+ sum(ResolutionWidth + 24), sum(ResolutionWidth + 25), sum(ResolutionWidth + 26), sum(ResolutionWidth + 27),
+ sum(ResolutionWidth + 28), sum(ResolutionWidth + 29), sum(ResolutionWidth + 30), sum(ResolutionWidth + 31),
+ sum(ResolutionWidth + 32), sum(ResolutionWidth + 33), sum(ResolutionWidth + 34), sum(ResolutionWidth + 35),
+ sum(ResolutionWidth + 36), sum(ResolutionWidth + 37), sum(ResolutionWidth + 38), sum(ResolutionWidth + 39),
+ sum(ResolutionWidth + 40), sum(ResolutionWidth + 41), sum(ResolutionWidth + 42), sum(ResolutionWidth + 43),
+ sum(ResolutionWidth + 44), sum(ResolutionWidth + 45), sum(ResolutionWidth + 46), sum(ResolutionWidth + 47),
+ sum(ResolutionWidth + 48), sum(ResolutionWidth + 49), sum(ResolutionWidth + 50), sum(ResolutionWidth + 51),
+ sum(ResolutionWidth + 52), sum(ResolutionWidth + 53), sum(ResolutionWidth + 54), sum(ResolutionWidth + 55),
+ sum(ResolutionWidth + 56), sum(ResolutionWidth + 57), sum(ResolutionWidth + 58), sum(ResolutionWidth + 59),
+ sum(ResolutionWidth + 60), sum(ResolutionWidth + 61), sum(ResolutionWidth + 62), sum(ResolutionWidth + 63),
+ sum(ResolutionWidth + 64), sum(ResolutionWidth + 65), sum(ResolutionWidth + 66), sum(ResolutionWidth + 67),
+ sum(ResolutionWidth + 68), sum(ResolutionWidth + 69), sum(ResolutionWidth + 70), sum(ResolutionWidth + 71),
+ sum(ResolutionWidth + 72), sum(ResolutionWidth + 73), sum(ResolutionWidth + 74), sum(ResolutionWidth + 75),
+ sum(ResolutionWidth + 76), sum(ResolutionWidth + 77), sum(ResolutionWidth + 78), sum(ResolutionWidth + 79),
+ sum(ResolutionWidth + 80), sum(ResolutionWidth + 81), sum(ResolutionWidth + 82), sum(ResolutionWidth + 83),
+ sum(ResolutionWidth + 84), sum(ResolutionWidth + 85), sum(ResolutionWidth + 86), sum(ResolutionWidth + 87),
+ sum(ResolutionWidth + 88), sum(ResolutionWidth + 89)
+FROM {table};
+-- q31
+SELECT SearchEngineID, ClientIP, count(*) AS c, sum(Refresh), avg(ResolutionWidth)
+FROM {table} WHERE SearchPhrase != '' GROUP BY SearchEngineID, ClientIP ORDER BY c DESC LIMIT 10;
+-- q32
+SELECT WatchID, ClientIP, count(*) AS c, sum(Refresh), avg(ResolutionWidth)
+FROM {table} WHERE SearchPhrase != '' GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;
+-- q33
+SELECT WatchID, ClientIP, count(*) AS c, sum(Refresh), avg(ResolutionWidth)
+FROM {table} GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;
+-- q34
+SELECT URL, count(*) AS c FROM {table} GROUP BY URL ORDER BY c DESC LIMIT 10;
+-- q35
+SELECT UserID, URL, count(*) AS c FROM {table} GROUP BY UserID, URL ORDER BY c DESC LIMIT 10;
+-- q36
+SELECT x0, x1, x2, x3, count(*) AS c
+FROM {table}
+GROUP BY ClientIP as x0, ClientIP - 1 as x1, ClientIP - 2 as x2, ClientIP - 3 as x3 ORDER BY c DESC LIMIT 10;
+-- q37
+SELECT URL, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND DontCountHits == 0
+ AND Refresh == 0 AND URL != ''
+GROUP BY URL ORDER BY PageViews DESC LIMIT 10;
+-- q38
+SELECT Title, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND DontCountHits == 0 AND
+ Refresh == 0 AND Title != ''
+GROUP BY Title ORDER BY PageViews DESC LIMIT 10;
+-- q39
+SELECT URL, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND Refresh == 0 AND
+ IsLink != 0 AND IsDownload == 0
+GROUP BY URL ORDER BY PageViews DESC LIMIT 1000;
+-- q40
+SELECT TraficSourceID, SearchEngineID, AdvEngineID, Src, Dst, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND Refresh == 0
+GROUP BY
+ TraficSourceID, SearchEngineID, AdvEngineID, IF(SearchEngineID = 0 AND AdvEngineID = 0, Referer, '') AS Src,
+ URL AS Dst
+ORDER BY PageViews DESC LIMIT 1000;
+-- q41
+SELECT URLHash, EventDate, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND Refresh == 0 AND
+ TraficSourceID IN (-1, 6) AND RefererHash = Digest::Md5HalfMix('http://example.ru/')
+GROUP BY URLHash, EventDate ORDER BY PageViews DESC LIMIT 100;
+-- q42
+SELECT WindowClientWidth, WindowClientHeight, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-31') AND Refresh == 0 AND
+ DontCountHits == 0 AND URLHash = Digest::Md5HalfMix('http://example.ru/')
+GROUP BY WindowClientWidth, WindowClientHeight ORDER BY PageViews DESC LIMIT 10000;
+-- q43
+SELECT Minute, count(*) AS PageViews
+FROM {table}
+WHERE
+ CounterID = 62 AND EventDate >= Date('2013-07-01') AND EventDate <= Date('2013-07-02') AND Refresh == 0 AND
+ DontCountHits == 0
+GROUP BY DateTime::ToSeconds(EventTime)/60 As Minute ORDER BY Minute
diff --git a/ydb/public/lib/ydb_cli/commands/click_bench_schema.sql b/ydb/public/lib/ydb_cli/commands/click_bench_schema.sql
new file mode 100644
index 00000000000..30cd0bcbc9f
--- /dev/null
+++ b/ydb/public/lib/ydb_cli/commands/click_bench_schema.sql
@@ -0,0 +1,112 @@
+--!syntax_v1
+CREATE TABLE `{table}` (
+ HashUserID Uint64,
+ CounterID Uint64,
+ EventDate Date,
+ AdvEngineID Uint64,
+ Age Uint64,
+ BrowserCountry String,
+ BrowserLanguage String,
+ CLID Uint64,
+ ClientEventTime Datetime,
+ ClientIP Uint64,
+ ClientTimeZone Int64,
+ CodeVersion Uint64,
+ ConnectTiming Uint64,
+ CookieEnable Uint64,
+ CounterClass Int64,
+ DNSTiming Uint64,
+ DontCountHits Uint64,
+ EventTime Datetime,
+ FUniqID Uint64,
+ FetchTiming Uint64,
+ FlashMajor Uint64,
+ FlashMinor Uint64,
+ FlashMinor2 String,
+ FromTag String,
+ GoodEvent Int64,
+ HID Uint64,
+ HTTPError Uint64,
+ HasGCLID Uint64,
+ HistoryLength Int64,
+ HitColor String,
+ IPNetworkID Uint64,
+ Income Uint64,
+ Interests Uint64,
+ IsArtifical Uint64,
+ IsDownload Uint64,
+ IsEvent Uint64,
+ IsLink Uint64,
+ IsMobile Uint64,
+ IsNotBounce Uint64,
+ IsOldCounter Uint64,
+ IsParameter Uint64,
+ JavaEnable Uint64,
+ JavascriptEnable Uint64,
+ LocalEventTime Datetime,
+ MobilePhone Uint64,
+ MobilePhoneModel String,
+ NetMajor Uint64,
+ NetMinor Uint64,
+ OS Uint64,
+ OpenerName Int64,
+ OpenstatAdID String,
+ OpenstatCampaignID String,
+ OpenstatServiceName String,
+ OpenstatSourceID String,
+ OriginalURL String,
+ PageCharset String,
+ ParamCurrency String,
+ ParamCurrencyID Uint64,
+ ParamOrderID String,
+ ParamPrice Int64,
+ Params String,
+ Referer String,
+ RefererCategoryID Uint64,
+ RefererHash Uint64,
+ RefererRegionID Uint64,
+ Refresh Uint64,
+ RegionID Uint64,
+ RemoteIP Uint64,
+ ResolutionDepth Uint64,
+ ResolutionHeight Uint64,
+ ResolutionWidth Uint64,
+ ResponseEndTiming Uint64,
+ ResponseStartTiming Uint64,
+ Robotness Uint64,
+ SearchEngineID Uint64,
+ SearchPhrase String,
+ SendTiming Uint64,
+ Sex Uint64,
+ SilverlightVersion1 Uint64,
+ SilverlightVersion2 Uint64,
+ SilverlightVersion3 Uint64,
+ SilverlightVersion4 Uint64,
+ SocialAction String,
+ SocialNetwork String,
+ SocialSourceNetworkID Uint64,
+ SocialSourcePage String,
+ Title String,
+ TraficSourceID Int64,
+ URL String,
+ URLCategoryID Uint64,
+ URLHash Uint64,
+ URLRegionID Uint64,
+ UTMCampaign String,
+ UTMContent String,
+ UTMMedium String,
+ UTMSource String,
+ UTMTerm String,
+ UserAgent Uint64,
+ UserAgentMajor Uint64,
+ UserAgentMinor String,
+ UserID Uint64,
+ WatchID Uint64,
+ WindowClientHeight Uint64,
+ WindowClientWidth Uint64,
+ WindowName Int64,
+ WithHash Uint64,
+ PRIMARY KEY (CounterID, EventDate, UserID, WatchID, ClientEventTime, LocalEventTime, EventTime, ClientIP, ConnectTiming, HistoryLength)
+) WITH (
+ AUTO_PARTITIONING_BY_SIZE = ENABLED
+);
diff --git a/ydb/public/lib/ydb_cli/commands/stock_workload.h b/ydb/public/lib/ydb_cli/commands/stock_workload.h
index c2e12fb7cc9..8ed4317a7f7 100644
--- a/ydb/public/lib/ydb_cli/commands/stock_workload.h
+++ b/ydb/public/lib/ydb_cli/commands/stock_workload.h
@@ -95,4 +95,4 @@ private:
};
}
-} \ No newline at end of file
+}
diff --git a/ydb/public/lib/ydb_cli/commands/ydb_workload.cpp b/ydb/public/lib/ydb_cli/commands/ydb_workload.cpp
index 559fe8171ef..1f9a5bf85b7 100644
--- a/ydb/public/lib/ydb_cli/commands/ydb_workload.cpp
+++ b/ydb/public/lib/ydb_cli/commands/ydb_workload.cpp
@@ -2,6 +2,7 @@
#include "stock_workload.h"
#include "kv_workload.h"
+#include "click_bench.h"
#include <ydb/library/workload/workload_factory.h>
#include <ydb/public/lib/ydb_cli/commands/ydb_common.h>
@@ -36,6 +37,7 @@ TCommandWorkload::TCommandWorkload()
{
AddCommand(std::make_unique<TCommandStock>());
AddCommand(std::make_unique<TCommandKv>());
+// AddCommand(std::make_unique<TCommandClickBench>());
}
TWorkloadCommand::TWorkloadCommand(const TString& name, const std::initializer_list<TString>& aliases, const TString& description)