
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ем или напрямую другими системами

Alexander
15.12.2016
08:54:10
Графики тоже, конечно, можно построить, но это уже мелочи

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 (назовем это так) не должно быть слишком сложно

Admin
ERROR: S client not available

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 — эт нет

Google


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 или составного - вполне.


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 ?
Выглядит так что действительно никак, но можно попробовать придумать