implement ORDER BY optimization for some other meta-storages

This commit is contained in:
CurtizJ 2019-12-11 16:09:46 +03:00
parent fd5b23730e
commit 6834fbf03d
6 changed files with 21 additions and 13 deletions

View File

@ -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<const MergeTreeData *>(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;

View File

@ -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;

View File

@ -58,7 +58,7 @@ struct SyntaxAnalyzerResult;
using SyntaxAnalyzerResultPtr = std::shared_ptr<const SyntaxAnalyzerResult>;
class ReadInOrderOptimizer;
using ReadInOrderOptimizerPtr = std::shared_ptr<ReadInOrderOptimizer>;
using ReadInOrderOptimizerPtr = std::shared_ptr<const ReadInOrderOptimizer>;
/** 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)

View File

@ -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);
}

View File

@ -15,6 +15,7 @@
#include <DataStreams/IBlockOutputStream.h>
#include <Storages/StorageFactory.h>
#include <Storages/ReadInOrderOptimizer.h>
#include <Common/typeid_cast.h>
@ -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);

View File

@ -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<SelectQueryInfo &>(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)