fix prewhere

This commit is contained in:
CurtizJ 2020-02-05 19:42:27 +03:00
parent 3c1735d996
commit db47ef923c
5 changed files with 26 additions and 8 deletions

View File

@ -324,7 +324,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(
table_id = storage->getStorageID();
}
auto analyze = [&] ()
auto analyze = [&] (bool try_move_to_prewhere = true)
{
syntax_analyzer_result = SyntaxAnalyzer(*context, options).analyze(
query_ptr, source_header.getNamesAndTypesList(), required_result_column_names, storage, NamesAndTypesList());
@ -397,7 +397,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(
throw Exception("PREWHERE is not supported if the table is filtered by row-level security expression", ErrorCodes::ILLEGAL_PREWHERE);
/// Calculate structure of the result.
result_header = getSampleBlockImpl();
result_header = getSampleBlockImpl(try_move_to_prewhere);
};
analyze();
@ -425,8 +425,13 @@ InterpreterSelectQuery::InterpreterSelectQuery(
query.setExpression(ASTSelectQuery::Expression::WHERE, makeASTFunction("and", query.prewhere()->clone(), query.where()->clone()));
need_analyze_again = true;
}
if (need_analyze_again)
analyze();
{
/// Do not try move conditions to PREWHERE for the second time.
/// Otherwise, we won't be able to fallback from inefficient PREWHERE to WHERE later.
analyze(/* try_move_to_prewhere = */ false);
}
/// If there is no WHERE, filter blocks as usual
if (query.prewhere() && !query.where())
@ -509,7 +514,7 @@ QueryPipeline InterpreterSelectQuery::executeWithProcessors()
}
Block InterpreterSelectQuery::getSampleBlockImpl()
Block InterpreterSelectQuery::getSampleBlockImpl(bool try_move_to_prewhere)
{
auto & query = getSelectQuery();
const Settings & settings = context->getSettingsRef();
@ -533,7 +538,7 @@ Block InterpreterSelectQuery::getSampleBlockImpl()
current_info.sets = query_analyzer->getPreparedSets();
/// Try transferring some condition from WHERE to PREWHERE if enabled and viable
if (settings.optimize_move_to_prewhere && query.where() && !query.prewhere() && !query.final())
if (settings.optimize_move_to_prewhere && try_move_to_prewhere && query.where() && !query.prewhere() && !query.final())
MergeTreeWhereOptimizer{current_info, *context, merge_tree,
syntax_analyzer_result->requiredSourceColumns(), log};
};

View File

@ -104,7 +104,7 @@ private:
ASTSelectQuery & getSelectQuery() { return query_ptr->as<ASTSelectQuery &>(); }
Block getSampleBlockImpl();
Block getSampleBlockImpl(bool try_move_to_prewhere);
struct Pipeline
{

View File

@ -431,9 +431,11 @@ void MergeTreeRangeReader::ReadResult::setFilter(const ColumnPtr & new_filter)
}
ConstantFilterDescription const_description(*new_filter);
if (const_description.always_false)
if (const_description.always_true)
setFilterConstTrue();
else if (const_description.always_false)
clear();
else if (!const_description.always_true)
else
{
FilterDescription filter_description(*new_filter);
filter_holder = filter_description.data_holder ? filter_description.data_holder : new_filter;

View File

@ -0,0 +1,2 @@
99
4950

View File

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS t;
CREATE TABLE t (a Int, b Int, c Int) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO t SELECT number, number * 2, number * 3 FROM numbers(100);
SELECT count() FROM t PREWHERE NOT ignore(a) WHERE b > 0;
SELECT sum(a) FROM t PREWHERE isNotNull(a) WHERE isNotNull(b) AND c > 0;
DROP TABLE t;