Skip to content
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

Conditional computations. #2272

Merged
merged 9 commits into from
May 1, 2018
Merged

Conversation

ilyshnikova
Copy link
Contributor

I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en

В этом реквесте содержится правка, которая позволяет вычислять аргументы функции and не везде, а только на определенных подмножествах строк.

Включается эта функциональность опцией клиента enable_conditional_computation. По-дефолту, функциональность выклчена

Пример работы

ubuntu.members.linode.com :) select arrayMap(x -> x and modulo(1,x), [0,1,2]);

SELECT arrayMap(x -> (x AND (1 % x)), [0, 1, 2])

Received exception from server (version 1.1.54380):
Code: 153. DB::Exception: Received from localhost:9000, ::1. DB::Exception: Division by zero. 

0 rows in set. Elapsed: 0.402 sec. 

ubuntu.members.linode.com :) set enable_conditional_computation=1;

SET enable_conditional_computation = 1

Ok.

0 rows in set. Elapsed: 0.002 sec. 

ubuntu.members.linode.com :) select arrayMap(x -> x and modulo(1,x), [0,1,2]);

SELECT arrayMap(x -> (x AND (1 % x)), [0, 1, 2])

┌─arrayMap(lambda(tuple(x), and(x, modulo(1, x))), [0, 1, 2])─┐
│ [0,0,1]                                                     │
└─────────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.011 sec. 

ubuntu.members.linode.com :)

Особенность реквеста: приходится пробрасывать в execute количество входных строк, из-за кейсов, где аргумент фукнции "and" может не иметь никаких входных параметров и угадать число строк результата невозможно внутри выполнения функции, только подсказать ей снаружи, как в примере f and emptyArrayUInt8()

В остальном все просто: добавлены функции проекции, восстановления и взятия композиции проекций и построен способ выбора экшенов, который использует эти функции для вычисления результата.

@@ -67,6 +69,10 @@ struct ExpressionAction
std::string result_name;
DataTypePtr result_type;

/// For projections
Copy link
Contributor

@ludv1x ludv1x Apr 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Плохое имя, т.к. в этом же и смежных классах под проекцией понимается совршенно другая вещь.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Очень не хватает комментариев в коде, без них сложно разобраться в алгоритме.


void ExpressionAnalyzer::getRootActions(const ASTPtr & ast, bool no_subqueries, bool only_consts, ExpressionActionsPtr & actions)
{
ScopeStack scopes(actions, settings);
getActionsImpl(ast, no_subqueries, only_consts, scopes);
ProjectionManipulatorPtr projection_manipulator;
if (!isThereArrayJoin(ast) && settings.enable_conditional_computation && !only_consts)
Copy link
Contributor

@ludv1x ludv1x Apr 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут не совсем очевидна мотивация.
По идее если при выполнении arrayJoin делать replicate() виртуальных столбцов с масками, то должно все работать (?).
Еще есть вариант выполнять все arrayJoin'ы после всех обычных функций.

В текущем варианте это усложняет код тем, что приходится поддерживать dummy реализации всего из ProjectionManipulator.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Это не первочередное проблема)

@@ -231,6 +231,11 @@ class ColumnVector final : public COWPtrHelper<IColumn, ColumnVector<T>>
return UInt64(data[n]);
}

UInt8 getUInt8(size_t n) const override
{
return UInt8(!!data[n]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

То, что возвращает функция, не соответствует названию.
Для 0.1 getUInt8 вернет 1, а getUInt64 - 0. Возможно, назвать функцию как getBoolRepresentation() или как-то аналогично?

auto col_res = ColumnUInt8::create();
auto & vec_res = col_res->getData();
vec_res.resize(data_column->size());
for (size_t i = 0; i < data_column->size(); ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{ должна быть на новой строке

auto & vec_res = col_res->getData();
vec_res.resize(data_column->size());
for (size_t i = 0; i < data_column->size(); ++i) {
if (data_column->getUInt8(i)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно проверить, что виртуальный вызов на каждую строку не тормозит. Например, добавить typeid_cast для ColumnUInt8 и сравнить на простом запросе. (select sum(number % 3 == 1 and number % 5 == 2) form system.numbers limit 10000000).


DataTypePtr FunctionProject::getReturnTypeImpl(const DataTypes & arguments) const
{
return arguments[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Должен ли 2-й аргумент иметь тип UInt8? Если да, то нужно добавить проверку.


DataTypePtr FunctionBuildProjectionComposition::getReturnTypeImpl(const DataTypes & /*arguments*/) const
{
return std::make_shared<DataTypeUInt8>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если оба аргумента имеют тип UInt8, нужно это проверить.

std::vector<size_t> override_indices(arguments.size() - 1, 0);
for (size_t i = 0; i < projection_column->size(); ++i) {
size_t argument_index = projection_column->getUInt8(i) + 1;
col_res->insertFrom(*block.getByPosition(arguments[argument_index]).column, ++override_indices[argument_index]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Идея микрооптимизации: запоминать последовательности одинаковых индексов и использовать insertRangeFrom

vec_res[i] = second_projection_column->getUInt8(current_reverse_index++);
}
}
block.getByPosition(result).column = std::move(col_res);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не помешает проверить, что current_reverse_index == second_projection_column->size()

size_t argument_index = projection_column->getUInt8(i) + 1;
col_res->insertFrom(*block.getByPosition(arguments[argument_index]).column, ++override_indices[argument_index]);
}
block.getByPosition(result).column = std::move(col_res);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Проверить, что override_indices совпадает с размером колонок.

@@ -58,6 +58,8 @@ struct ExpressionAction

/// Reorder and rename the columns, delete the extra ones. The same column names are allowed in the result.
PROJECT,

MEASURE_INPUT_ROWS_COUNT,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не хватает комментария

@@ -67,6 +69,11 @@ struct ExpressionAction
std::string result_name;
DataTypePtr result_type;

/// For conditional projections (projections on subset of rows)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Из комментария не вполне понятно, для чего нужны эти поля и как MEASURE_INPUT_ROWS_COUNT.
По коду смог понять, что output_row_projection_expression используется для результата MEASURE_INPUT_ROWS_COUNT, а input_row_projection_expression и is_row_projection_complementary в методе execute для того, чтобы получить размер колонки для результата add_column и apply_function. Верно ли это? (Комментарий такого стиля был бы полезен)

@alexey-milovidov alexey-milovidov merged commit 9be89bd into ClickHouse:master May 1, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 6, 2018
alexey-milovidov added a commit that referenced this pull request May 7, 2018
alexey-milovidov added a commit that referenced this pull request May 7, 2018
alexey-milovidov added a commit that referenced this pull request May 7, 2018
alexey-milovidov added a commit that referenced this pull request May 7, 2018
@filimonov filimonov mentioned this pull request May 17, 2018
proller pushed a commit to proller/ClickHouse that referenced this pull request Nov 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants