mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-15 10:52:30 +00:00
It might be working
This commit is contained in:
parent
daaa3db809
commit
569f42d1d9
@ -336,6 +336,7 @@ class IColumn;
|
||||
M(Bool, optimize_throw_if_noop, false, "If setting is enabled and OPTIMIZE query didn't actually assign a merge then an explanatory exception is thrown", 0) \
|
||||
M(Bool, use_index_for_in_with_subqueries, true, "Try using an index if there is a subquery or a table expression on the right side of the IN operator.", 0) \
|
||||
M(UInt64, use_index_for_in_with_subqueries_max_values, 0, "The maximum size of set in the right hand side of the IN operator to use table index for filtering. It allows to avoid performance degradation and higher memory usage due to preparation of additional data structures for large queries. Zero means no limit.", 0) \
|
||||
M(Bool, analyze_index_with_space_filling_curves, true, "If a table has a space-filling curve in its index, e.g. `ORDER BY mortonEncode(x, y)`, and the query has conditions on its arguments, e.g. `x >= 10 AND x <= 20 AND y >= 20 AND y <= 30`, use the space-filling curve for index analysis.", 0) \
|
||||
M(Bool, joined_subquery_requires_alias, true, "Force joined subqueries and table functions to have aliases for correct name qualification.", 0) \
|
||||
M(Bool, empty_result_for_aggregation_by_empty_set, false, "Return empty result when aggregating without keys on empty set.", 0) \
|
||||
M(Bool, empty_result_for_aggregation_by_constant_keys_on_empty_set, true, "Return empty result when aggregating by constant keys on empty set.", 0) \
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <Functions/CastOverloadResolver.h>
|
||||
#include <Functions/IFunction.h>
|
||||
#include <Common/FieldVisitorToString.h>
|
||||
#include <Common/MortonUtils.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Columns/ColumnSet.h>
|
||||
#include <Interpreters/convertFieldToType.h>
|
||||
@ -729,7 +730,6 @@ void KeyCondition::getAllSpaceFillingCurves()
|
||||
{
|
||||
/// So far the only supported function is mortonEncode (Morton curve).
|
||||
|
||||
size_t key_column_pos = 0;
|
||||
for (const auto & action : key_expr->getActions())
|
||||
{
|
||||
if (action.node->type == ActionsDAG::ActionType::FUNCTION
|
||||
@ -738,7 +738,7 @@ void KeyCondition::getAllSpaceFillingCurves()
|
||||
{
|
||||
SpaceFillingCurveDescription curve;
|
||||
curve.function_name = action.node->function_base->getName();
|
||||
curve.key_column_pos = key_column_pos;
|
||||
curve.key_column_pos = key_columns.at(action.node->result_name);
|
||||
for (const auto & child : action.node->children)
|
||||
{
|
||||
/// All arguments should be regular input columns.
|
||||
@ -755,7 +755,6 @@ void KeyCondition::getAllSpaceFillingCurves()
|
||||
if (!curve.arguments.empty())
|
||||
key_space_filling_curves.push_back(std::move(curve));
|
||||
}
|
||||
++key_column_pos;
|
||||
}
|
||||
}
|
||||
|
||||
@ -787,7 +786,8 @@ KeyCondition::KeyCondition(
|
||||
++key_index;
|
||||
}
|
||||
|
||||
getAllSpaceFillingCurves();
|
||||
if (context.getSettingsRef().analyze_index_with_space_filling_curves)
|
||||
getAllSpaceFillingCurves();
|
||||
|
||||
ASTPtr filter_node;
|
||||
if (query)
|
||||
@ -863,7 +863,8 @@ KeyCondition::KeyCondition(
|
||||
++key_index;
|
||||
}
|
||||
|
||||
getAllSpaceFillingCurves();
|
||||
if (context.getSettingsRef().analyze_index_with_space_filling_curves)
|
||||
getAllSpaceFillingCurves();
|
||||
|
||||
if (!filter_dag)
|
||||
{
|
||||
@ -2158,7 +2159,7 @@ KeyCondition::Description KeyCondition::getDescription() const
|
||||
}
|
||||
|
||||
if (rpn_stack.size() != 1)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected stack size in KeyCondition::checkInRange");
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected stack size in KeyCondition::getDescription");
|
||||
|
||||
std::vector<String> key_names(key_columns.size());
|
||||
std::vector<bool> is_key_used(key_columns.size(), false);
|
||||
@ -2383,14 +2384,14 @@ BoolMask KeyCondition::checkInRange(
|
||||
key_ranges.push_back(Range::createWholeUniverseWithoutNull());
|
||||
}
|
||||
|
||||
std::cerr << "Checking for: [";
|
||||
/* std::cerr << "Checking for: [";
|
||||
for (size_t i = 0; i != used_key_size; ++i)
|
||||
std::cerr << (i != 0 ? ", " : "") << applyVisitor(FieldVisitorToString(), left_keys[i]);
|
||||
std::cerr << " ... ";
|
||||
|
||||
for (size_t i = 0; i != used_key_size; ++i)
|
||||
std::cerr << (i != 0 ? ", " : "") << applyVisitor(FieldVisitorToString(), right_keys[i]);
|
||||
std::cerr << "]\n";
|
||||
std::cerr << "]\n";*/
|
||||
|
||||
return forAnyHyperrectangle(used_key_size, left_keys, right_keys, true, true, key_ranges, data_types, 0, initial_mask,
|
||||
[&] (const Hyperrectangle & key_ranges_hyperrectangle)
|
||||
@ -2534,7 +2535,13 @@ BoolMask KeyCondition::checkInHyperrectangle(
|
||||
std::vector<BoolMask> rpn_stack;
|
||||
for (const auto & element : rpn)
|
||||
{
|
||||
if (element.function == RPNElement::FUNCTION_UNKNOWN)
|
||||
if (element.argument_num_of_space_filling_curve.has_value())
|
||||
{
|
||||
/// If a condition on argument of a space filling curve wasn't collapsed into FUNCTION_ARGS_IN_HYPERRECTANGLE,
|
||||
/// we cannot process it.
|
||||
rpn_stack.emplace_back(true, true);
|
||||
}
|
||||
else if (element.function == RPNElement::FUNCTION_UNKNOWN)
|
||||
{
|
||||
rpn_stack.emplace_back(true, true);
|
||||
}
|
||||
@ -2576,9 +2583,51 @@ BoolMask KeyCondition::checkInHyperrectangle(
|
||||
/// We unpack the range of a space filling curve into hyperrectangles of their arguments,
|
||||
/// and then check the intersection of them with the given hyperrectangle from RPN.
|
||||
|
||||
const Range * key_range = &hyperrectangle[element.key_column];
|
||||
Range key_range = hyperrectangle[element.key_column];
|
||||
|
||||
|
||||
/// The only possible result type of a space filling curve is UInt64.
|
||||
/// We also only check bounded ranges.
|
||||
if (key_range.left.getType() == Field::Types::UInt64
|
||||
&& key_range.right.getType() == Field::Types::UInt64)
|
||||
{
|
||||
key_range.shrinkToIncludedIfPossible();
|
||||
|
||||
size_t num_dimensions = element.space_filling_curve_args_hyperrectangle.size();
|
||||
|
||||
/// Let's support only the case of 2d, because I'm not confident in other cases.
|
||||
if (num_dimensions == 2)
|
||||
{
|
||||
UInt64 left = key_range.left.get<UInt64>();
|
||||
UInt64 right = key_range.right.get<UInt64>();
|
||||
|
||||
BoolMask mask(false, true);
|
||||
mortonIntervalToHyperrectangles<2>(left, right,
|
||||
[&](std::array<std::pair<UInt64, UInt64>, 2> morton_hyperrectangle)
|
||||
{
|
||||
BoolMask current_intersection(true, false);
|
||||
for (size_t dim = 0; dim < num_dimensions; ++dim)
|
||||
{
|
||||
const Range & condition_arg_range = element.space_filling_curve_args_hyperrectangle[dim];
|
||||
const Range morton_arg_range(
|
||||
morton_hyperrectangle[dim].first, true,
|
||||
morton_hyperrectangle[dim].second, true);
|
||||
|
||||
bool intersects = condition_arg_range.intersectsRange(morton_arg_range);
|
||||
bool contains = condition_arg_range.containsRange(morton_arg_range);
|
||||
|
||||
current_intersection = current_intersection & BoolMask(intersects, !contains);
|
||||
}
|
||||
|
||||
mask = mask | current_intersection;
|
||||
});
|
||||
|
||||
rpn_stack.emplace_back(mask);
|
||||
}
|
||||
else
|
||||
rpn_stack.emplace_back(true, true);
|
||||
}
|
||||
else
|
||||
rpn_stack.emplace_back(true, true);
|
||||
}
|
||||
else if (
|
||||
element.function == RPNElement::FUNCTION_IS_NULL
|
||||
@ -2642,7 +2691,7 @@ BoolMask KeyCondition::checkInHyperrectangle(
|
||||
}
|
||||
|
||||
if (rpn_stack.size() != 1)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected stack size in KeyCondition::checkInRange");
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected stack size in KeyCondition::checkInHyperrectangle");
|
||||
|
||||
return rpn_stack[0];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user