Merge pull request #40740 from amosbird/row-policy-index-fix-1

Use index when row_policy_filter is always false
This commit is contained in:
Kruglov Pavel 2022-08-31 18:46:14 +02:00 committed by GitHub
commit 86516d3bb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 1 deletions

View File

@ -865,6 +865,7 @@ MergeTreeDataSelectAnalysisResultPtr ReadFromMergeTree::selectRangesToRead(
size_t total_parts = parts.size(); size_t total_parts = parts.size();
/// TODO Support row_policy_filter and additional_filters
auto part_values = MergeTreeDataSelectExecutor::filterPartsByVirtualColumns(data, parts, query_info.query, context); auto part_values = MergeTreeDataSelectExecutor::filterPartsByVirtualColumns(data, parts, query_info.query, context);
if (part_values && part_values->empty()) if (part_values && part_values->empty())
return std::make_shared<MergeTreeDataSelectAnalysisResult>(MergeTreeDataSelectAnalysisResult{.result = std::move(result)}); return std::make_shared<MergeTreeDataSelectAnalysisResult>(MergeTreeDataSelectAnalysisResult{.result = std::move(result)});
@ -923,6 +924,9 @@ MergeTreeDataSelectAnalysisResultPtr ReadFromMergeTree::selectRangesToRead(
} }
LOG_DEBUG(log, "Key condition: {}", key_condition->toString()); LOG_DEBUG(log, "Key condition: {}", key_condition->toString());
if (key_condition->alwaysFalse())
return std::make_shared<MergeTreeDataSelectAnalysisResult>(MergeTreeDataSelectAnalysisResult{.result = std::move(result)});
const auto & select = query_info.query->as<ASTSelectQuery &>(); const auto & select = query_info.query->as<ASTSelectQuery &>();
size_t total_marks_pk = 0; size_t total_marks_pk = 0;

View File

@ -2463,7 +2463,6 @@ BoolMask KeyCondition::checkInHyperrectangle(
return rpn_stack[0]; return rpn_stack[0];
} }
bool KeyCondition::mayBeTrueInRange( bool KeyCondition::mayBeTrueInRange(
size_t used_key_size, size_t used_key_size,
const FieldRef * left_keys, const FieldRef * left_keys,
@ -2474,6 +2473,7 @@ bool KeyCondition::mayBeTrueInRange(
} }
String KeyCondition::RPNElement::toString() const { return toString("column " + std::to_string(key_column), false); } String KeyCondition::RPNElement::toString() const { return toString("column " + std::to_string(key_column), false); }
String KeyCondition::RPNElement::toString(std::string_view column_name, bool print_constants) const String KeyCondition::RPNElement::toString(std::string_view column_name, bool print_constants) const
{ {
auto print_wrapped_column = [this, &column_name, print_constants](WriteBuffer & buf) auto print_wrapped_column = [this, &column_name, print_constants](WriteBuffer & buf)
@ -2563,10 +2563,12 @@ bool KeyCondition::alwaysUnknownOrTrue() const
{ {
return unknownOrAlwaysTrue(false); return unknownOrAlwaysTrue(false);
} }
bool KeyCondition::anyUnknownOrAlwaysTrue() const bool KeyCondition::anyUnknownOrAlwaysTrue() const
{ {
return unknownOrAlwaysTrue(true); return unknownOrAlwaysTrue(true);
} }
bool KeyCondition::unknownOrAlwaysTrue(bool unknown_any) const bool KeyCondition::unknownOrAlwaysTrue(bool unknown_any) const
{ {
std::vector<UInt8> rpn_stack; std::vector<UInt8> rpn_stack;
@ -2627,6 +2629,80 @@ bool KeyCondition::unknownOrAlwaysTrue(bool unknown_any) const
return rpn_stack[0]; return rpn_stack[0];
} }
bool KeyCondition::alwaysFalse() const
{
/// 0: always_false, 1: always_true, 2: non_const
std::vector<UInt8> rpn_stack;
for (const auto & element : rpn)
{
if (element.function == RPNElement::ALWAYS_TRUE)
{
rpn_stack.push_back(1);
}
else if (element.function == RPNElement::ALWAYS_FALSE)
{
rpn_stack.push_back(0);
}
else if (element.function == RPNElement::FUNCTION_NOT_IN_RANGE
|| element.function == RPNElement::FUNCTION_IN_RANGE
|| element.function == RPNElement::FUNCTION_IN_SET
|| element.function == RPNElement::FUNCTION_NOT_IN_SET
|| element.function == RPNElement::FUNCTION_IS_NULL
|| element.function == RPNElement::FUNCTION_IS_NOT_NULL
|| element.function == RPNElement::FUNCTION_UNKNOWN)
{
rpn_stack.push_back(2);
}
else if (element.function == RPNElement::FUNCTION_NOT)
{
assert(!rpn_stack.empty());
auto & arg = rpn_stack.back();
if (arg == 0)
arg = 1;
else if (arg == 1)
arg = 0;
}
else if (element.function == RPNElement::FUNCTION_AND)
{
assert(!rpn_stack.empty());
auto arg1 = rpn_stack.back();
rpn_stack.pop_back();
auto arg2 = rpn_stack.back();
if (arg1 == 0 || arg2 == 0)
rpn_stack.back() = 0;
else if (arg1 == 1 && arg2 == 1)
rpn_stack.back() = 1;
else
rpn_stack.back() = 2;
}
else if (element.function == RPNElement::FUNCTION_OR)
{
assert(!rpn_stack.empty());
auto arg1 = rpn_stack.back();
rpn_stack.pop_back();
auto arg2 = rpn_stack.back();
if (arg1 == 1 || arg2 == 1)
rpn_stack.back() = 1;
else if (arg1 == 0 && arg2 == 0)
rpn_stack.back() = 0;
else
rpn_stack.back() = 2;
}
else
throw Exception("Unexpected function type in KeyCondition::RPNElement", ErrorCodes::LOGICAL_ERROR);
}
if (rpn_stack.size() != 1)
throw Exception("Unexpected stack size in KeyCondition::alwaysFalse", ErrorCodes::LOGICAL_ERROR);
return rpn_stack[0] == 0;
}
size_t KeyCondition::getMaxKeyColumn() const size_t KeyCondition::getMaxKeyColumn() const
{ {

View File

@ -279,6 +279,8 @@ public:
/// Does not allow any FUNCTION_UNKNOWN (will instantly return true). /// Does not allow any FUNCTION_UNKNOWN (will instantly return true).
bool anyUnknownOrAlwaysTrue() const; bool anyUnknownOrAlwaysTrue() const;
bool alwaysFalse() const;
/// Get the maximum number of the key element used in the condition. /// Get the maximum number of the key element used in the condition.
size_t getMaxKeyColumn() const; size_t getMaxKeyColumn() const;

View File

@ -0,0 +1,17 @@
drop table if exists tbl;
create table tbl (s String, i int) engine MergeTree order by i;
insert into tbl values ('123', 123);
drop row policy if exists filter on tbl;
create row policy filter on tbl using 0 to all;
set max_rows_to_read = 0;
select * from tbl;
drop row policy filter on tbl;
drop table tbl;