From 928adb2b38f8d1e067c7a7d81aa337e89092e7ea Mon Sep 17 00:00:00 2001 From: vdimir Date: Thu, 18 Aug 2022 09:13:47 +0000 Subject: [PATCH] [WIP] Limit number of analyze for one query --- src/Interpreters/Context.h | 21 +++++++++++++++++++ src/Interpreters/InterpreterSelectQuery.cpp | 11 ++++++++++ .../02337_join_analyze_stuck.reference | 0 .../0_stateless/02337_join_analyze_stuck.sql | 15 +++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 tests/queries/0_stateless/02337_join_analyze_stuck.reference create mode 100644 tests/queries/0_stateless/02337_join_analyze_stuck.sql diff --git a/src/Interpreters/Context.h b/src/Interpreters/Context.h index ea03b8e6586..13d57c0b962 100644 --- a/src/Interpreters/Context.h +++ b/src/Interpreters/Context.h @@ -367,6 +367,27 @@ public: // Top-level OpenTelemetry trace context for the query. Makes sense only for a query context. OpenTelemetryTraceContext query_trace_context; + /// Some counters for current query execution. + /// Most of them are workarounds and should be removed in the future. + struct KitchenSink + { + std::atomic analyze_counter = 0; + + KitchenSink() = default; + + KitchenSink(const KitchenSink & rhs) + : analyze_counter(rhs.analyze_counter.load()) + {} + + KitchenSink & operator=(const KitchenSink & rhs) + { + analyze_counter = rhs.analyze_counter.load(); + return *this; + } + }; + + KitchenSink kitchen_sink; + private: using SampleBlockCache = std::unordered_map; mutable SampleBlockCache sample_block_cache; diff --git a/src/Interpreters/InterpreterSelectQuery.cpp b/src/Interpreters/InterpreterSelectQuery.cpp index 76f199d8e41..ac7cc4c1b4e 100644 --- a/src/Interpreters/InterpreterSelectQuery.cpp +++ b/src/Interpreters/InterpreterSelectQuery.cpp @@ -98,6 +98,7 @@ namespace ErrorCodes extern const int SAMPLING_NOT_SUPPORTED; extern const int ILLEGAL_FINAL; extern const int ILLEGAL_PREWHERE; + extern const int TOO_DEEP_PIPELINE; extern const int TOO_MANY_COLUMNS; extern const int LOGICAL_ERROR; extern const int NOT_IMPLEMENTED; @@ -496,6 +497,14 @@ InterpreterSelectQuery::InterpreterSelectQuery( auto analyze = [&] (bool try_move_to_prewhere) { + if (context->hasQueryContext()) + { + std::atomic & current_query_analyze_count = context->getQueryContext()->kitchen_sink.analyze_counter; + ++current_query_analyze_count; + if (settings.max_pipeline_depth && current_query_analyze_count >= settings.max_pipeline_depth) + throw DB::Exception(ErrorCodes::TOO_DEEP_PIPELINE, "Query analyze overflow. Try to increase `max_pipeline_depth` or simplify the query"); + } + /// Allow push down and other optimizations for VIEW: replace with subquery and rewrite it. ASTPtr view_table; if (view) @@ -639,6 +648,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( analyze(shouldMoveToPrewhere()); bool need_analyze_again = false; + if (analysis_result.prewhere_constant_filter_description.always_false || analysis_result.prewhere_constant_filter_description.always_true) { if (analysis_result.prewhere_constant_filter_description.always_true) @@ -647,6 +657,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( query.setExpression(ASTSelectQuery::Expression::PREWHERE, std::make_shared(0u)); need_analyze_again = true; } + if (analysis_result.where_constant_filter_description.always_false || analysis_result.where_constant_filter_description.always_true) { if (analysis_result.where_constant_filter_description.always_true) diff --git a/tests/queries/0_stateless/02337_join_analyze_stuck.reference b/tests/queries/0_stateless/02337_join_analyze_stuck.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/02337_join_analyze_stuck.sql b/tests/queries/0_stateless/02337_join_analyze_stuck.sql new file mode 100644 index 00000000000..9bdc418f028 --- /dev/null +++ b/tests/queries/0_stateless/02337_join_analyze_stuck.sql @@ -0,0 +1,15 @@ +-- Tags: long + +-- https://github.com/ClickHouse/ClickHouse/issues/21557 + +SET max_pipeline_depth = 1000; + +EXPLAIN SYNTAX +WITH + x AS ( SELECT number FROM numbers(10) ), + cross_sales AS ( + SELECT 1 AS xx + FROM x, x AS d1, x AS d2, x AS d3, x AS d4, x AS d5, x AS d6, x AS d7, x AS d8, x AS d9 + WHERE x.number = d9.number + ) +SELECT xx FROM cross_sales WHERE xx = 2000; -- { serverError TOO_DEEP_PIPELINE }