
Stepan
14.12.2016
18:22:33
Найс, спасибо

Roman
14.12.2016
18:30:41
И как у Александра дела — закончил он миграцию с Вертики на КХ?

Stanislav
14.12.2016
18:36:18
https://mariadb.com/products/mariadb-columnstore

Igor
14.12.2016
18:37:17
http://greenplum.org/ еще есть на основе постгреса

Google

Konstantin
14.12.2016
18:40:24
Мужчина из крупной мебельной компании задаёт жёсткие вопросы )

Stanislav
14.12.2016
18:45:00
А что случилось с DELETE? Его сломали?

Anatoly
14.12.2016
18:45:48
его не было

Igor
14.12.2016
18:52:49
угу. есть только ALTER TABLE DROP PARTITION

Vladislav
14.12.2016
19:30:06

Shine
14.12.2016
19:34:03
роадмап скромный, были же еще апдейты заявлены, оконные функции )

Vladislav
14.12.2016
19:34:58
вообще, до сих пор вроде видео нет, а очень бы хотелось посмотреть

Alexey
14.12.2016
21:12:26

Igor
14.12.2016
21:16:19

Alexander
14.12.2016
21:59:12


Valeriy
14.12.2016
22:24:17
Чем можно объяснить, что фулскан селект (в запросе нет where) по полям, которых нет в ключе, выполняется дольше на более жирном ключе, чем на коротком, хотя по данным из гугл.групс длина ключа тут вообще никак не должна влиять?
Есть две одинаковые по данным таблицы, разница только в ключе - в первой он (advertiser_id, date, sample_id), во второй - (advertiser_id, sample_id). Запрос выглядит так: select argMax(pad_id, u), max(u) from (select pad_id, uniq(user_id) as u from events group by pad_id). На первой таблице он выполняется за 29 сек, на второй - за 20. Кэш прогрет, беру времена самого быстрого из трех запросов, после первого запроса чтения с диска уже не производится. Аналогичные результаты и в случае, если pad_id заменить здесь на advertiser_id, т.е. использовать поле из ключа, но только первое.


Alexey
14.12.2016
22:27:31
Данные занимают одинаковый размер на диске?
Возможно (хотя и маловероятно), что после сортировки по одному из вариантов ключа, данные сжались лучше.
Таблицы на одном сервере? Насколько отличается разбиение на "куски": SELECT * FROM system.parts WHERE active AND table = '...'

Google

Valeriy
14.12.2016
22:36:34
Данные занимают разный размер. Таблица с более жирным ключом занимает 161 Гб, с коротким - 81 Гб. OPTIMIZE TABLE делал обеим таблицам. Разница выглядит слишком большой, а полей в таблице много. Загляну-ка, что там внутри.
Таблицы на одном сервере.
В каждой упомянутый селект выдает по одной записи (по одной партиции), данных там неделя, лежат в пределах одного месяца.
В данных странное - колонки advertiser_id одинакового размера, а вот все остальные колонки в первой жирной таблице раза в два больше, чем во второй.
Особенно sample_id.bin отличается - 27450М против 4777M.
А date.bin - единственное поле, которое в первой таблице на порядок меньше, чем во второй - видимо, как раз за счет отсортированности в ключе.

Alexey
14.12.2016
22:53:13
Данные в таблицах реально одинаковые или разные?
Количество строк, хотя бы.

Valeriy
14.12.2016
22:55:29
Данные одинаковые. Обе таблицы наливались через INSERT into SELECT * FROM - из третьей таблицы. Количество строк одинаково, все запросы выдают одинаковые результаты.
Еще интересный, с моей точки зрения, момент, что изначально у меня была таблица на 1 день, и занимала она 20 Гб. Я ее размножил в 7 раз, делая 7 раз в другую таблицу с идентичным описанием запросом insert from (select ...) из исходной, где при селекте к timestamp прибавлял N * 86400, и полученная таблица стала занимать 192 Гб (сама, после всех мерджей, и такой же размер остался после OPTIMIZE TABLE), т.е. она выросла более, чем в 7 раз.


Alexey
14.12.2016
23:10:06
В первом случае, если sample_id - довольно тяжёлый столбец, то он лучше сожмётся в случае ключа
(advertiser_id, sample_id)
чем
(advertiser_id, date, sample_id)
из-за более локального расположения.
Еще интересный, с моей точки зрения, момент, что изначально у меня была таблица на 1 день, и занимала она 20 Гб. Я ее размножил в 7 раз, делая 7 раз в другую таблицу с идентичным описанием запросом insert from (select ...) из исходной, где при селекте к timestamp прибавлял N * 86400, и полученная таблица стала занимать 192 Гб (сама, после всех мерджей, и такой же размер остался после OPTIMIZE TABLE), т.е. она выросла более, чем в 7 раз.
Здесь возможно, если данные почему-то оказались больше перемешаны для каждого фиксированного значения первичного ключа. То есть, сжатие всё объясняет. Но на реальных кейсах такое поведение встречается редко.

Valeriy
14.12.2016
23:22:47
Вероятно, это может все объяснить. Спасибо.

Виктор
15.12.2016
01:07:40
Чем вам zk не нравится то всем?
Всерьёз спрашиваю
ZK в кликхаусе много для чего. Leader election, распределённый транзакционный kv, всякие listeners
У нас в Метрике огромные zk и особл проблем с ними нет
Немного неудобно, это правда, свои проблемы есть
Но надежность как у гаечного ключа хорошего

Maksim
15.12.2016
03:00:42
Соглашусь, zk норм, работает.

Konstantin
15.12.2016
06:19:34
Устанавливается тяжело. И неудобно, да. И религиозные соображения - из исходников его трудно собрать (на грани невозможного).

Alexey
15.12.2016
07:05:29
Витя, насколько я понял zk сложнее настроить у некоторых с этим проблемы. Просили даже показать как вы в метрике его используете, с какими опциями.

Alexander
15.12.2016
08:10:42
У нас тоже никаких проблем с ZK. Тонкости есть, скажем, cross-dc, но сам ZK работает замечательно

Google

Alexey
15.12.2016
08:15:01
ну наверное проблема в том, что он не модный не молодежный
вот если бы на GO
ну крайняк на Rust, то может быть
у меня связка ZK+Kafka+Flink+ES молотит > 15000 документов в секунду
на 3-ех узлах невыдающихся

Иван
15.12.2016
08:26:21
Flink сам консьюмит с кафки? У него нормально с ребалансингом и коммитами?

Roman
15.12.2016
08:30:18
ну наверное проблема в том, что он не модный не молодежный
Кстати о птичках — на zk работает кластеризация вполне коммерческого софта — Tableau Server. Но zk там хорошо скрыт под капотом, практически не требует администрирования. Так что наверное дело не в молодежности, а в необходимости разбираться в дополнительной софтине с собственной логикой и скелетами в шкафу. https://onlinehelp.tableau.com/current/server/en-us/server_process_coordination.htm #tableau

Alexey
15.12.2016
08:40:58

Alexander
15.12.2016
08:44:05
> @roman_kolchin
Александр, вы, оказывается, уже в этом чатике! А какой tool используют ваши аналитики для собственного ad hoc анализа данных в КХ? Они освоили его SQL?
У нас собственный middleware (на Scala), который генерирует SQL запросы. Его пришлось полностью переписать под КХ, чтобы заменить обычные SQL-джойны на вложенные и словари.

Roman
15.12.2016
08:46:26

Alexander
15.12.2016
08:53:49
Нет, больше как раз таблицы. middleware выдает клиенту json или csv (несколько форматов), который дальше используется UIем или напрямую другими системами
Графики тоже, конечно, можно построить, но это уже мелочи

Roman
15.12.2016
08:54:47
А каким образом клиенты запросы формируют? У вас есть какой-то птичий язык для этих целей?
Или вручную заранее настроенные sql запросы, которые зашиты в middleware?

Alexander
15.12.2016
08:56:06
Ну можно скзать, что птичий язык. Есть API, через который передаются набор измерений, метрик, фильтров и проч

Roman
15.12.2016
08:56:54
Если Scala/JVM, то olap4j случайно не используете?

Alexander
15.12.2016
09:28:07
Нет, все самописное

Roman
15.12.2016
09:36:16
Нет, все самописное
Молодцы вы. А я все мечтаю, что MDX когда-нибудь над КХ появится :) Через Mondrian хотя бы, но с блэкджеком, словарями и использованием массивов в запросах чтоб все очень быстро :)

Alexander
15.12.2016
10:02:55
Вчера на митапе звучало предложение об MDX. Но это после нормальных джойнов

Google

Roman
15.12.2016
10:11:10
Я изучал этот вопрос _теоретически_ — на первый взгляд сейчас уже всего хватает (словари + словарные функции + массивы), чтобы сделать эффективную трансляцию. Эффективную — в смысле трансляции развезистой клюквы большого mdx-запроса в единственный однопроходный запрос к базе, без лишних union'ов. Но транслятор нужен именно под синтаксис КХ.
Join'ы не помогут сами по себе. Синтаксически мб и заработает, но лагать будет дико из-за большого количества вложенных запросов и кучи union'ов.

Alexander
15.12.2016
10:13:05
Это был вопрос к Яндексу. Странслировать MDX в CH-SQL (назовем это так) не должно быть слишком сложно

Roman
15.12.2016
10:13:52

Alexander
15.12.2016
10:14:57
Это тоже один из вопросов, которые обсуждали :) Все просят Яндекс, сделайте то, сделайте это, но мало кто контрибьютит сам

Alexey
15.12.2016
10:16:00
Посмотрите, вот интересный продукт: https://github.com/Wondersoft/olaper
Автор говорит, что есть желание сделать интеграцию с ClickHouse.

Roman
15.12.2016
10:16:35

Alexander
15.12.2016
10:24:56
Насколько я его понимаю, ему нужен клиент, под которого это можно изначально сделать, а потом отдать всем. Так как проект не самый простой, а ресурсов работать забесплатно у его компании нет.

Roman
15.12.2016
10:27:25


Alexander
15.12.2016
10:38:53
Нет, нам не нужен, мы не используем MDX

Nick
15.12.2016
11:34:21
Коллеги, привет. У нас внешние словари имеют ключи guid'ы. Можно ли как-то их подключить?

Vladislav
15.12.2016
11:35:23

Alexander
15.12.2016
14:29:24

Maksim
15.12.2016
14:30:47
мы для uuid-ов воткнули две строчки, которые превращают uuid в FixedString(16) и обратно
но вот для primary key — эт нет


Alexey
15.12.2016
14:57:51
Коллеги, привет. У нас внешние словари имеют ключи guid'ы. Можно ли как-то их подключить?
Можно использовать complex_key-словари. Они поддерживают произвольные типы ключей.
Словари по составному ключу:
Конфиг словаря с составным ключом отличается двумя вещами:
В качестве layout указывается complex_key_hashed или complex_key_cache.
Указывается несколько атрибутов в structure/key.
Пример:
<layout>
<complex_key_hashed />
</layout>
<structure>
<key>
<attribute>
<name>uid</name>
<type>UInt64</type>
</attribute>
<attribute>
<name>order_id</name>
<type>UInt32</type>
</attribute>
</key>
<attribute>
<name>has_access</name>
<type>UInt8</type>
<null_value>0</null_value>
</attribute>
</structure>
Для использования словаря с составным ключём, в функции для работы со словарями, в качестве аргумента-ключа передаётся кортеж.
Пример: dictGetString('dict', 'attr', (k1, k2)).
В качестве элементов ключа, поддерживаются произвольные типы данных (в том числе, строки).
Не смотря на название, complex_key_-словарь может иметь и один компонент в качестве ключа. То есть, не составной ключ.
При этом, в отличие от обычных словарей, этот ключ может иметь любой тип.
В этом случае, в функции для работы со словарями, нужно передавать кортеж из одного элемента.
Пример: dictGetString('dict', 'attr', tuple(k)).
- как видно, для описания кортежа из одного элемента, используется функция tuple.
Для типов UInt32 и подобных, я не рекомендую использовать complex_-словари, так как это будет менее эффективно, чем обычные.
А вот для типа String или составного - вполне.

Google

Igor
15.12.2016
18:33:58
Подскажите, а как можно посчитать median() в CollapsingMergeTree без использования модификатора FINAL ?


Nick
15.12.2016
19:15:14
Можно использовать complex_key-словари. Они поддерживают произвольные типы ключей.
Словари по составному ключу:
Конфиг словаря с составным ключом отличается двумя вещами:
В качестве layout указывается complex_key_hashed или complex_key_cache.
Указывается несколько атрибутов в structure/key.
Пример:
<layout>
<complex_key_hashed />
</layout>
<structure>
<key>
<attribute>
<name>uid</name>
<type>UInt64</type>
</attribute>
<attribute>
<name>order_id</name>
<type>UInt32</type>
</attribute>
</key>
<attribute>
<name>has_access</name>
<type>UInt8</type>
<null_value>0</null_value>
</attribute>
</structure>
Для использования словаря с составным ключём, в функции для работы со словарями, в качестве аргумента-ключа передаётся кортеж.
Пример: dictGetString('dict', 'attr', (k1, k2)).
В качестве элементов ключа, поддерживаются произвольные типы данных (в том числе, строки).
Не смотря на название, complex_key_-словарь может иметь и один компонент в качестве ключа. То есть, не составной ключ.
При этом, в отличие от обычных словарей, этот ключ может иметь любой тип.
В этом случае, в функции для работы со словарями, нужно передавать кортеж из одного элемента.
Пример: dictGetString('dict', 'attr', tuple(k)).
- как видно, для описания кортежа из одного элемента, используется функция tuple.
Для типов UInt32 и подобных, я не рекомендую использовать complex_-словари, так как это будет менее эффективно, чем обычные.
А вот для типа String или составного - вполне.
Спасибо! Но все-таки guid является не строкой, а отдельным типом данных (да и места меньше занимает). Планируется ли их полноценная поддержка?


Alexey
15.12.2016
19:22:10
Как отдельного типа данных - нет. Но недавно добавили возможность удобного преобразования из бинарного вида FixedString(16) в текст и обратно.

Maksim
15.12.2016
19:38:38

Alexey
15.12.2016
20:39:51
Если есть желание, можно здесь нажать на upvote:
https://news.ycombinator.com/item?id=13183758
Мелочь, а может быть человеку будет приятно.

Igor
15.12.2016
20:46:44
я думаю помочь ему в разработке, sqlalchemy всяко популярнее самописной clickhouse-orm
блин, а там она и используется %))

Alexey
15.12.2016
21:54:18

Igor
15.12.2016
22:03:05
спасибо, тоже так думал- искал пути решения, но вдруг есть скрытый "ход")
еще вопрос, про ЯМ, у нас хранится значение, допустим сколько пользователь провел времени на странице - аналогичное ЯМ, и каждые 15 секунд это значение схлопывается и увеличивается в рамках сессии, получается если в ЯМ тоже каллапс движек - вы считаете через "avg" т.е sum(sign).... ?

Alexey
15.12.2016
22:04:33
Да, через sum(x * sign) / sum(sign).

Igor
15.12.2016
22:05:01
спасибо!

Виктор
16.12.2016
00:31:11
Вот это отличный вопрос кстати
Подскажите, а как можно посчитать median() в CollapsingMergeTree без использования модификатора FINAL ?
Выглядит так что действительно никак, но можно попробовать придумать