Fix projections with GROUP/ORDER BY in query and optimize_aggregation_in_order

With projections, GROUP BY/ORDER BY in query, optimize_aggregation_in_order,
GROUP BY's InputOrderInfo was used incorrectly for ORDER BY.

Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2022-05-19 08:00:38 +03:00
parent ef1773f444
commit e32b695775
3 changed files with 34 additions and 21 deletions

View File

@ -1168,6 +1168,12 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
LOG_TRACE(log, "{} -> {}", QueryProcessingStage::toString(from_stage), QueryProcessingStage::toString(options.to_stage));
}
if (query_info.projection && query_info.projection->input_order_info && query_info.input_order_info)
throw Exception("InputOrderInfo is set for projection and for query", ErrorCodes::LOGICAL_ERROR);
InputOrderInfoPtr input_order_info_for_order;
if (!expressions.need_aggregate)
input_order_info_for_order = query_info.projection ? query_info.projection->input_order_info : query_info.input_order_info;
if (options.to_stage > QueryProcessingStage::FetchColumns)
{
auto preliminary_sort = [&]()
@ -1183,10 +1189,7 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
&& !expressions.has_window)
{
if (expressions.has_order_by)
executeOrder(
query_plan,
query_info.input_order_info ? query_info.input_order_info
: (query_info.projection ? query_info.projection->input_order_info : nullptr));
executeOrder(query_plan, input_order_info_for_order);
if (expressions.has_order_by && query.limitLength())
executeDistinct(query_plan, false, expressions.selected_columns, true);
@ -1311,16 +1314,9 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
executeWhere(query_plan, expressions.before_where, expressions.remove_where_filter);
if (expressions.need_aggregate)
{
executeAggregation(
query_plan, expressions.before_aggregation, aggregate_overflow_row, aggregate_final, query_info.input_order_info);
/// We need to reset input order info, so that executeOrder can't use it
query_info.input_order_info.reset();
if (query_info.projection)
query_info.projection->input_order_info.reset();
}
// Now we must execute:
// 1) expressions before window functions,
// 2) window functions,
@ -1455,10 +1451,7 @@ void InterpreterSelectQuery::executeImpl(QueryPlan & query_plan, std::optional<P
&& !(query.group_by_with_totals && !aggregate_final))
executeMergeSorted(query_plan, "for ORDER BY, without aggregation");
else /// Otherwise, just sort.
executeOrder(
query_plan,
query_info.input_order_info ? query_info.input_order_info
: (query_info.projection ? query_info.projection->input_order_info : nullptr));
executeOrder(query_plan, input_order_info_for_order);
}
/** Optimization - if there are several sources and there is LIMIT, then first apply the preliminary LIMIT,
@ -2747,12 +2740,6 @@ void InterpreterSelectQuery::executeExtremes(QueryPlan & query_plan)
void InterpreterSelectQuery::executeSubqueriesInSetsAndJoins(QueryPlan & query_plan, SubqueriesForSets & subqueries_for_sets)
{
// const auto & input_order_info = query_info.input_order_info
// ? query_info.input_order_info
// : (query_info.projection ? query_info.projection->input_order_info : nullptr);
// if (input_order_info)
// executeMergeSorted(query_plan, input_order_info->order_key_prefix_descr, 0, "before creating sets for subqueries and joins");
const Settings & settings = context->getSettingsRef();
SizeLimits limits(settings.max_rows_to_transfer, settings.max_bytes_to_transfer, settings.transfer_overflow_mode);

View File

@ -0,0 +1,13 @@
-- { echoOn }
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=0, optimize_read_in_order=0;
15 480
14 450
13 420
12 390
11 360
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=1, optimize_read_in_order=1;
15 480
14 450
13 420
12 390
11 360

View File

@ -0,0 +1,13 @@
-- Tags: no-s3-storage
drop table if exists test_agg_proj_02302;
create table test_agg_proj_02302 (x Int32, y Int32, PROJECTION x_plus_y (select sum(x - y), argMax(x, y) group by x + y)) ENGINE = MergeTree order by tuple() settings index_granularity = 1;
insert into test_agg_proj_02302 select intDiv(number, 2), -intDiv(number,3) - 1 from numbers(100);
-- { echoOn }
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=0, optimize_read_in_order=0;
select x + y, sum(x - y) as s from test_agg_proj_02302 group by x + y order by s desc limit 5 settings allow_experimental_projection_optimization=1, optimize_aggregation_in_order=1, optimize_read_in_order=1;
-- { echoOff }
drop table test_agg_proj_02302;