-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Fix condition not being moved to prewhere in case there is a row policy #85118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6b09e4e
5c691ff
d876c64
ffd0c1c
362afcd
aea5975
5ceb04a
b524f9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,9 +48,8 @@ ActionsDAG splitAndFillPrewhereInfo( | |
| const std::list<const ActionsDAG::Node *> & prewhere_nodes_list) | ||
| { | ||
| prewhere_info->need_filter = true; | ||
| prewhere_info->remove_prewhere_column = remove_prewhere_column; | ||
|
|
||
| if (prewhere_info->remove_prewhere_column) | ||
| if (remove_prewhere_column) | ||
| { | ||
| removeFromOutput(filter_expression, filter_column_name); | ||
| auto & outputs = filter_expression.getOutputs(); | ||
|
|
@@ -94,22 +93,55 @@ ActionsDAG splitAndFillPrewhereInfo( | |
| for (const auto * condition : prewhere_nodes_list) | ||
| conditions.push_back(split_result.split_nodes_mapping.at(condition)); | ||
|
|
||
| /// Is it possible that prewhere_info->prewhere_actions was not empty? | ||
| /// Not sure, but just in case let's merge it | ||
| if (prewhere_info->prewhere_actions) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing about this function All that needs to be done is to properly construct a DAG that is a conjuction of the optimized filter_expression + existing prewhere (preserving row level filters). I just don't know how to do it :). |
||
| { | ||
| split_result.first.mergeInplace(std::move(*prewhere_info->prewhere_actions)); | ||
|
|
||
| const auto * existing_prewhere_node = &split_result.first.findInOutputs(prewhere_info->prewhere_column_name); | ||
| conditions.push_back(existing_prewhere_node); | ||
|
|
||
| /// Should this be done after or before the mergeInPlace? | ||
| if (prewhere_info->remove_prewhere_column) | ||
| { | ||
| removeFromOutput(split_result.first, prewhere_info->prewhere_column_name); | ||
| // split_result.first.removeUnusedActions(); | ||
| } | ||
| } | ||
|
|
||
| { | ||
| std::unordered_set<const ActionsDAG::Node *> first_outputs( | ||
| split_result.first.getOutputs().begin(), split_result.first.getOutputs().end()); | ||
| for (const auto * input : split_result.first.getInputs()) | ||
| { | ||
| if (!first_outputs.contains(input)) | ||
| { | ||
| split_result.first.getOutputs().push_back(input); | ||
| /// Add column to second actions as input. | ||
| /// Do not add it to result, so it would be removed. | ||
| split_result.second.addInput(input->result_name, input->result_type); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Comment on lines
+106
to
+127
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still don't know what's the right procedure to merge these conditions. This was the closest I got to it (a few lines below it'll |
||
| prewhere_info->prewhere_actions = std::move(split_result.first); | ||
|
|
||
| if (conditions.size() == 1) | ||
| { | ||
| prewhere_info->remove_prewhere_column = remove_prewhere_column; | ||
| prewhere_info->prewhere_column_name = conditions.front()->result_name; | ||
| if (prewhere_info->remove_prewhere_column) | ||
| prewhere_info->prewhere_actions.getOutputs().push_back(conditions.front()); | ||
| prewhere_info->prewhere_actions->getOutputs().push_back(conditions.front()); | ||
| } | ||
| else | ||
| { | ||
| prewhere_info->remove_prewhere_column = true; | ||
|
|
||
| FunctionOverloadResolverPtr func_builder_and = std::make_unique<FunctionToOverloadResolverAdaptor>(std::make_shared<FunctionAnd>()); | ||
| const auto * node = &prewhere_info->prewhere_actions.addFunction(func_builder_and, std::move(conditions), {}); | ||
| const auto * node = &prewhere_info->prewhere_actions->addFunction(func_builder_and, std::move(conditions), {}); | ||
| prewhere_info->prewhere_column_name = node->result_name; | ||
| prewhere_info->prewhere_actions.getOutputs().push_back(node); | ||
| prewhere_info->prewhere_actions->getOutputs().push_back(node); | ||
| } | ||
|
|
||
| return std::move(split_result.second); | ||
|
|
@@ -140,10 +172,6 @@ void optimizePrewhere(Stack & stack, QueryPlan::Nodes &) | |
| if (!storage.canMoveConditionsToPrewhere()) | ||
| return; | ||
|
|
||
| const auto & storage_prewhere_info = source_step_with_filter->getPrewhereInfo(); | ||
| if (storage_prewhere_info) | ||
| return; | ||
|
|
||
| /// TODO: We can also check for UnionStep, such as StorageBuffer and local distributed plans. | ||
| QueryPlan::Node * filter_node = (stack.rbegin() + 1)->node; | ||
| auto * filter_step = typeid_cast<FilterStep *>(filter_node->step.get()); | ||
|
|
@@ -179,8 +207,10 @@ void optimizePrewhere(Stack & stack, QueryPlan::Nodes &) | |
|
|
||
| Names queried_columns = source_step_with_filter->requiredSourceColumns(); | ||
|
|
||
| const auto & storage_prewhere_info = source_step_with_filter->getPrewhereInfo(); | ||
|
|
||
| const auto & source_filter_actions_dag = source_step_with_filter->getFilterActionsDAG(); | ||
| MergeTreeWhereOptimizer where_optimizer{ | ||
| MergeTreeWhereOptimizer where_optimizer{ | ||
| std::move(column_compressed_sizes), | ||
| storage_metadata, | ||
| storage.getConditionSelectivityEstimatorByPredicate(storage_snapshot, source_filter_actions_dag ? &*source_filter_actions_dag : nullptr, context), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,8 @@ void optimizePrimaryKeyConditionAndLimit(const Stack & stack) | |
| const auto & storage_prewhere_info = source_step_with_filter->getPrewhereInfo(); | ||
| if (storage_prewhere_info) | ||
| { | ||
| source_step_with_filter->addFilter(storage_prewhere_info->prewhere_actions.clone(), storage_prewhere_info->prewhere_column_name); | ||
| if (storage_prewhere_info->prewhere_actions) | ||
| source_step_with_filter->addFilter(storage_prewhere_info->prewhere_actions->clone(), storage_prewhere_info->prewhere_column_name); | ||
| if (storage_prewhere_info->row_level_filter) | ||
| source_step_with_filter->addFilter(storage_prewhere_info->row_level_filter->clone(), storage_prewhere_info->row_level_column_name); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me this code looks rather worrying (don't mean actual change).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The limit should be applied only after all the filters. Also, it's used only in |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Just set prewhere manually.