Merge pull request #17458 from ClickHouse/merge-expressions

Merge expressions
This commit is contained in:
alesapin 2020-12-07 12:34:19 +03:00 committed by GitHub
commit 57f40e4260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 419 additions and 319 deletions

View File

@ -349,6 +349,16 @@ void ActionsDAG::removeUnusedActions()
stack.push(node);
}
/// We cannot remove arrayJoin because it changes the number of rows.
for (auto & node : nodes)
{
if (node.type == ActionType::ARRAY_JOIN && visited_nodes.count(&node) == 0)
{
visited_nodes.insert(&node);
stack.push(&node);
}
}
while (!stack.empty())
{
auto * node = stack.top();
@ -552,6 +562,15 @@ bool ActionsDAG::hasArrayJoin() const
return false;
}
bool ActionsDAG::hasStatefulFunctions() const
{
for (const auto & node : nodes)
if (node.type == ActionType::FUNCTION && node.function_base->isStateful())
return true;
return false;
}
bool ActionsDAG::empty() const
{
for (const auto & node : nodes)
@ -670,6 +689,111 @@ ActionsDAGPtr ActionsDAG::makeConvertingActions(
return actions_dag;
}
ActionsDAGPtr ActionsDAG::merge(ActionsDAG && first, ActionsDAG && second)
{
/// first: x (1), x (2), y ==> x (2), z, x (3)
/// second: x (1), x (2), x (3) ==> x (3), x (2), x (1)
/// merge: x (1), x (2), x (3), y =(first)=> x (3), y, x (2), z, x (4) =(second)=> y, z, x (4), x (2), x (3)
/// Will store merged result in `first`.
/// This map contains nodes which should be removed from `first` index, cause they are used as inputs for `second`.
std::unordered_set<Node *> removed_first_result;
/// Map inputs of `second` to nodes of `first`.
std::unordered_map<Node *, Node *> inputs_map;
/// Update inputs list.
{
/// Index may have multiple columns with same name. They also may be used by `second`. Order is important.
std::unordered_map<std::string_view, std::list<Node *>> first_result;
for (auto & node : first.index)
first_result[node->result_name].push_back(node);
for (auto & node : second.inputs)
{
auto it = first_result.find(node->result_name);
if (it == first_result.end() || it->second.empty())
{
if (first.settings.project_input)
throw Exception(ErrorCodes::LOGICAL_ERROR,
"Cannot find column {} in ActionsDAG result", node->result_name);
first.inputs.push_back(node);
}
else
{
inputs_map[node] = it->second.front();
removed_first_result.emplace(it->second.front());
it->second.pop_front();
}
}
}
/// Replace inputs from `second` to nodes from `first` result.
for (auto & node : second.nodes)
{
for (auto & child : node.children)
{
if (child->type == ActionType::INPUT)
{
auto it = inputs_map.find(child);
if (it != inputs_map.end())
child = it->second;
}
}
}
for (auto & node : second.index)
{
if (node->type == ActionType::INPUT)
{
auto it = inputs_map.find(node);
if (it != inputs_map.end())
node = it->second;
}
}
/// Update index.
if (second.settings.project_input)
{
first.index.swap(second.index);
first.settings.project_input = true;
}
else
{
/// Remove `second` inputs from index.
for (auto it = first.index.begin(); it != first.index.end();)
{
auto cur = it;
++it;
if (removed_first_result.count(*cur))
first.index.remove(cur);
}
for (auto * node : second.index)
first.index.insert(node);
}
first.nodes.splice(first.nodes.end(), std::move(second.nodes));
#if USE_EMBEDDED_COMPILER
if (first.compilation_cache == nullptr)
first.compilation_cache = second.compilation_cache;
#endif
first.settings.max_temporary_columns = std::max(first.settings.max_temporary_columns, second.settings.max_temporary_columns);
first.settings.max_temporary_non_const_columns = std::max(first.settings.max_temporary_non_const_columns, second.settings.max_temporary_non_const_columns);
first.settings.min_count_to_compile_expression = std::max(first.settings.min_count_to_compile_expression, second.settings.min_count_to_compile_expression);
first.settings.projected_output = second.settings.projected_output;
/// Drop unused inputs and, probably, some actions.
first.removeUnusedActions();
return std::make_shared<ActionsDAG>(std::move(first));
}
ActionsDAGPtr ActionsDAG::splitActionsBeforeArrayJoin(const NameSet & array_joined_columns)
{
/// Split DAG into two parts.

View File

@ -143,6 +143,15 @@ public:
map.erase(it);
}
void remove(std::list<Node *>::iterator it)
{
auto map_it = map.find((*it)->result_name);
if (map_it != map.end() && map_it->second == it)
map.erase(map_it);
list.erase(it);
}
void swap(Index & other)
{
list.swap(other.list);
@ -176,6 +185,7 @@ private:
public:
ActionsDAG() = default;
ActionsDAG(ActionsDAG &&) = default;
ActionsDAG(const ActionsDAG &) = delete;
ActionsDAG & operator=(const ActionsDAG &) = delete;
explicit ActionsDAG(const NamesAndTypesList & inputs_);
@ -222,6 +232,7 @@ public:
ActionsDAGPtr splitActionsBeforeArrayJoin(const NameSet & array_joined_columns);
bool hasArrayJoin() const;
bool hasStatefulFunctions() const;
bool empty() const; /// If actions only contain inputs.
const ActionsSettings & getSettings() const { return settings; }
@ -248,6 +259,12 @@ public:
MatchColumnsMode mode,
bool ignore_constant_values = false); /// Do not check that constants are same. Use value from result_header.
/// Create ActionsDAG which represents expression equivalent to applying lhs and rhs actions consequently.
/// Is used to replace `(first -> second)` expression chain to single `merge(first, second)` expression.
/// If first.settings.project_input is set, then outputs of `first` must include inputs of `second`.
/// Otherwise, any two actions may be combined.
static ActionsDAGPtr merge(ActionsDAG && first, ActionsDAG && second);
private:
Node & addNode(Node node, bool can_replace = false);
Node & getNode(const std::string & name);

View File

@ -484,6 +484,38 @@ static void tryLiftUpArrayJoin(QueryPlan::Node * parent_node, QueryPlan::Node *
: filter_step->updateInputStream(array_join_step->getOutputStream(), true);
}
static bool tryMergeExpressions(QueryPlan::Node * parent_node, QueryPlan::Node * child_node)
{
auto & parent = parent_node->step;
auto & child = child_node->step;
/// TODO: FilterStep
auto * parent_expr = typeid_cast<ExpressionStep *>(parent.get());
auto * child_expr = typeid_cast<ExpressionStep *>(child.get());
if (parent_expr && child_expr)
{
const auto & child_actions = child_expr->getExpression();
const auto & parent_actions = parent_expr->getExpression();
/// We cannot combine actions with arrayJoin and stateful function because we not always can reorder them.
/// Example: select rowNumberInBlock() from (select arrayJoin([1, 2]))
/// Such a query will return two zeroes if we combine actions together.
if (child_actions->hasArrayJoin() && parent_actions->hasStatefulFunctions())
return false;
auto merged = ActionsDAG::merge(std::move(*child_actions), std::move(*parent_actions));
auto expr = std::make_unique<ExpressionStep>(child_expr->getInputStreams().front(), merged);
expr->setStepDescription(parent_expr->getStepDescription() + " + " + child_expr->getStepDescription());
parent_node->step = std::move(expr);
parent_node->children.swap(child_node->children);
return true;
}
return false;
}
void QueryPlan::optimize()
{
struct Frame
@ -503,7 +535,11 @@ void QueryPlan::optimize()
{
/// First entrance, try push down.
if (frame.node->children.size() == 1)
{
tryPushDownLimit(frame.node->step, frame.node->children.front());
while (tryMergeExpressions(frame.node, frame.node->children.front()));
}
}
if (frame.next_child < frame.node->children.size())

View File

@ -1,8 +1,5 @@
Expression (Projection)
Expression (Projection + Before ORDER BY and SELECT)
Header: x UInt8
Expression (Before ORDER BY and SELECT)
Header: dummy UInt8
1 UInt8
SettingQuotaAndLimits (Set limits and quota after reading from storage)
Header: dummy UInt8
ReadFromStorage (SystemOne)

View File

@ -1,5 +1,3 @@
(Expression)
ExpressionTransform
(Expression)
ExpressionTransform
(Aggregating)

View File

@ -1,324 +1,252 @@
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Distinct
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Union
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)
Expression (Projection)
Expression (Before ORDER BY and SELECT)
Expression (Projection + Before ORDER BY and SELECT)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (SystemOne)