diff --git a/dbms/src/Storages/ReadInOrderOptimizer.cpp b/dbms/src/Storages/ReadInOrderOptimizer.cpp index 460c93d7ac8..2e7dcf2a803 100644 --- a/dbms/src/Storages/ReadInOrderOptimizer.cpp +++ b/dbms/src/Storages/ReadInOrderOptimizer.cpp @@ -27,7 +27,7 @@ ReadInOrderOptimizer::ReadInOrderOptimizer( forbidden_columns.insert(elem.first); } -InputSortingInfoPtr ReadInOrderOptimizer::analyze(const StoragePtr & storage) +InputSortingInfoPtr ReadInOrderOptimizer::analyze(const StoragePtr & storage) const { const MergeTreeData * merge_tree = dynamic_cast(storage.get()); if (!merge_tree || !merge_tree->hasSortingKey()) @@ -51,10 +51,6 @@ InputSortingInfoPtr ReadInOrderOptimizer::analyze(const StoragePtr & storage) order_key_prefix_descr.push_back(required_sort_description[i]); else { - const auto & input_columns = elements_actions[i]->getRequiredColumnsWithTypes(); - if (input_columns.size() != 1 || input_columns.front().name != sorting_key_columns[i]) - break; - bool first = true; for (const auto & action : elements_actions[i]->getActions()) { @@ -69,6 +65,12 @@ InputSortingInfoPtr ReadInOrderOptimizer::analyze(const StoragePtr & storage) else first = false; + if (action.argument_names.size() != 1 || action.argument_names.at(0) != sorting_key_columns[i]) + { + current_direction = 0; + break; + } + const auto & func = *action.function_base; if (!func.hasInformationAboutMonotonicity()) { @@ -76,7 +78,7 @@ InputSortingInfoPtr ReadInOrderOptimizer::analyze(const StoragePtr & storage) break; } - auto monotonicity = func.getMonotonicityForRange(*input_columns.front().type, {}, {}); + auto monotonicity = func.getMonotonicityForRange(*func.getArgumentTypes().at(0), {}, {}); if (!monotonicity.is_monotonic) { current_direction = 0; diff --git a/dbms/src/Storages/ReadInOrderOptimizer.h b/dbms/src/Storages/ReadInOrderOptimizer.h index a08c2005e32..63ad13b3163 100644 --- a/dbms/src/Storages/ReadInOrderOptimizer.h +++ b/dbms/src/Storages/ReadInOrderOptimizer.h @@ -20,7 +20,7 @@ public: const SortDescription & required_sort_description, const SyntaxAnalyzerResultPtr & syntax_result); - InputSortingInfoPtr analyze(const StoragePtr & storage); + InputSortingInfoPtr analyze(const StoragePtr & storage) const; private: ManyExpressionActions elements_actions; diff --git a/dbms/src/Storages/SelectQueryInfo.h b/dbms/src/Storages/SelectQueryInfo.h index 0ce21f999c4..11907151575 100644 --- a/dbms/src/Storages/SelectQueryInfo.h +++ b/dbms/src/Storages/SelectQueryInfo.h @@ -58,7 +58,7 @@ struct SyntaxAnalyzerResult; using SyntaxAnalyzerResultPtr = std::shared_ptr; class ReadInOrderOptimizer; -using ReadInOrderOptimizerPtr = std::shared_ptr; +using ReadInOrderOptimizerPtr = std::shared_ptr; /** Query along with some additional data, * that can be used during query processing @@ -72,9 +72,9 @@ struct SelectQueryInfo PrewhereInfoPtr prewhere_info; - InputSortingInfoPtr input_sorting_info; - ReadInOrderOptimizerPtr order_by_optimizer; + /// We can modify it while reading from storage + mutable InputSortingInfoPtr input_sorting_info; /// Prepared sets are used for indices by storage engine. /// Example: x IN (1, 2, 3) diff --git a/dbms/src/Storages/StorageBuffer.cpp b/dbms/src/Storages/StorageBuffer.cpp index 15e5c0f9d41..4683b665b10 100644 --- a/dbms/src/Storages/StorageBuffer.cpp +++ b/dbms/src/Storages/StorageBuffer.cpp @@ -165,6 +165,9 @@ BlockInputStreams StorageBuffer::read( if (dst_has_same_structure) { + if (query_info.order_by_optimizer) + query_info.input_sorting_info = query_info.order_by_optimizer->analyze(destination); + /// The destination table has the same structure of the requested columns and we can simply read blocks from there. streams_from_dst = destination->read(column_names, query_info, context, processed_stage, max_block_size, num_streams); } diff --git a/dbms/src/Storages/StorageMaterializedView.cpp b/dbms/src/Storages/StorageMaterializedView.cpp index 24a6461bdab..33b16631770 100644 --- a/dbms/src/Storages/StorageMaterializedView.cpp +++ b/dbms/src/Storages/StorageMaterializedView.cpp @@ -15,6 +15,7 @@ #include #include +#include #include @@ -200,6 +201,9 @@ BlockInputStreams StorageMaterializedView::read( { auto storage = getTargetTable(); auto lock = storage->lockStructureForShare(false, context.getCurrentQueryId()); + if (query_info.order_by_optimizer) + query_info.input_sorting_info = query_info.order_by_optimizer->analyze(storage); + auto streams = storage->read(column_names, query_info, context, processed_stage, max_block_size, num_streams); for (auto & stream : streams) stream->addTableLock(lock); diff --git a/dbms/src/Storages/StorageMerge.cpp b/dbms/src/Storages/StorageMerge.cpp index 23116a9dfef..4c86596ba05 100644 --- a/dbms/src/Storages/StorageMerge.cpp +++ b/dbms/src/Storages/StorageMerge.cpp @@ -217,15 +217,14 @@ BlockInputStreams StorageMerge::read( auto current_info = query_info.order_by_optimizer->analyze(it->first); if (it == selected_tables.begin()) input_sorting_info = current_info; - else if (!current_info || *current_info != *input_sorting_info) + else if (!current_info || (input_sorting_info && *current_info != *input_sorting_info)) input_sorting_info.reset(); if (!input_sorting_info) break; } - /// We have to modify query_info to create proper pipeline after read stage. - const_cast(query_info).input_sorting_info = input_sorting_info; + query_info.input_sorting_info = input_sorting_info; } for (auto it = selected_tables.begin(); it != selected_tables.end(); ++it)