Как стать автором
Обновить

Комментарии 9

зачем изобретать велосипеды \ костыли если есть kafka + ksql который заточен под это, да еще можно делать джоины оконных стримов
А еще есть Spark и Spark SQL… Он может не только со стримами работать. На планете есть много колоночных СУБД, в которых реализованы оконные функции.
Эта статья для аналитиков, которые работают с ClickHouse и которым может пригодиться этот функционал.

Когда делался groupArrayMovingSum, то он изначально назывался просто movingSum, но, впоследствии оказалось, что делать arrayJoin(groupArrayMovingSum(...)) или "ARRAY JOIN", для простого случая гораздо проще чем пытаться изобразить сложные случаи без массива.

Интересно, ClickHouse такие выражения оптимизирует?
Тот же SUM поверх окна вроде ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW всеми движками вычисляется инкрементально, то есть весь результат будет вычислен за линейное время.
sumArray(arrayMap(arraySlice)) если делать "по простому" создаст N массивов, будет считать сумму по каждому заново, и общая стоимость будет квадратичной. Теоретически и такое можно распознать и оптимизировать, но поскольку выражения более общие, то гораздо сложнее.

Боюсь что сам движок такие конструкции не оптимизирует. Вот комментарий (авторская орфография сохранена) из телеграм-канала «ClickHouse не тормозит». По большому счету предлагаемое решение костыль для реализации оконных функций на ClickHouse. Ждем релиз оконных функций Q4Y2020.
Denny Crane [not a Yandex bot], [18.08.20 16:59]
[В ответ на Ivan Solyakin]
arrayMap(x -> arraySlice(summ, 1, x), arrayEnumerate(summ)) AS cum_summ

лучше так не делать, жопа в том что summ будет размножаться лямбдой, т.е. arrayEnumerate(summ) создаст массив [1...1000], summ тысячу раз скопируется в памяти.

лучше избегать arrayEnumerate и передачи массива в лямбду, почти всегда это достижимо потому что все (нужные) ФВП принимают несколько массивов (аргументов лямбды)
Функции высшего порядка — особенностью этих функций является невозможность вызова функции внутри функции. То есть нельзя напрямую использовать, скажем, функцию arrayMap в качестве аргумента функции arrayFilter.

Строго говоря это не так, никто не мешает наслаивать их друг на друга.
SELECT arrayMap(x -> (x + 2), arrayFilter((x, y) -> (x = y), [1, 2, 3], [1, 3, 3])) AS res

┌─res───┐
│ [3,5] │
└───────┘

SELECT arrayMap(x -> arrayAll(s -> (s = 1), x), [[1, 1, 1], [1, 2, 3], [3], [1]]) AS res

┌─res───────┐
│ [1,0,0,1] │
└───────────┘

SELECT arrayFilter(x -> (arraySum(y -> (y % 2), x) > 4), [[1, 2, 3, 4], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]) AS res

┌─res───────────┐
│ [[1,3,5,7,9]] │
└───────────────┘
SELECT arrayFilter(x -> (arrayReduce('sum', arrayMap(y -> (y % 2), x)) > 4), [[1, 2, 3, 4], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]) AS res

┌─res───────────┐
│ [[1,3,5,7,9]] │
└───────────────┘
Вы правы. По этому вопросу я дал неверную информацию в статье.

Спасибо за статью. Я начинающий в Clickhouse, задача та же - переехать с BQ на CH.
Но про оконные функции в кликхаусе нашлось вот такое: https://clickhouse.com/docs/en/sql-reference/window-functions/ Это появилось уже после выхода статьи?

Да. Статья устарела, но, поскольку CH немного странно реализует оконные функции, в каких-то случаях подход может быть полезен.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации