Pull to refresh

Comments 204

Всё становится сложнее, если вам нужно выполнять запросы в интерактивном режиме по неагрегированным данным, поступающим в систему в реальном времени. Для решения этой задачи, открытых технологий подходящего качества до сих пор не существовало.


Kudu?
Насколько я понимаю, Kudu вполне себе конкурент для ClickHouse.
Но надо понимать, что Kudu находится в Beta и не рекомендуется к использованию в production (хотя, разработчики, конечно, активно к этому призывают). В то же время ClickHouse используется в Метрике (и не только), что является очень серьёзным кейсом.

Опишу первые впечатления:

ClickHouse выглядит интереснее, чем Kudu в плане возможностей. Намного более дружелюбен для использования. Не надо ковырять Impala, можно использовать человеческий и довольно приятный на первый взгляд клиент. Однако Kudu более прост в организации кластера и репликаций. Там не нужно никаких телодвижений по этому поводу. По скорости не понятно — надо бы сравнить и потестировать.

В общем, Яндекс круты. Продукт очень востребован, на рынке действительно нет таких OpenSource проектов (опять же, Kudu еще молод). Будем тестировать и пробовать.
Что примечательно, практически вся СУБД была создана одним человеком
В целом же молодцы, что открыли исходники! Очень интересно посмотреть, как оно работает изнутри
Вклад Алексея колоссален, но часть истории изменений, кажется, была потеряна при переезде на внешний GitHub.
Я специально проследил, чтобы история изменений не потерялась.
Посмотреть авторов коммитов можно так:

git log --format='%aN %aE' | sort | uniq -c | sort -rn

Проблема в том, что Github не связывает твой email с твоим аккаунтом.
Это можно исправить… напишу через пару часов лично.
Связывает, если указать это мыло в профиле.
Не согласен, двумя. Вы смотрите по частоте комитов. Alexey: LOC +2MM -1MM, PCartavyi: +1MM.
Конечно, возможно, что Алексей просто удалял все, что написал другой человек :)
Действитель очень круто, но я видимо слепой и не нашел интерфейсов к ЯП, неужели все только через HTTP\CLI\TCP?
Только эти интерфейсы документированы и ими можно пользоваться.

Есть также ODBC и JDBC драйверы.

ODBC драйвер находится в разработке. Он работает во многих случаях, но сейчас лучше им не пользоваться, если только вы не собираетесь самостоятельно его дорабатывать. Если очень надо, то можете найти его в исходниках.

JDBC драйвер находится в отдельном репозитории и на данный момент не выложен (это будем решать).
Очень интересует возможность обращаться к базе из разных языков программирования (Perl, Scala, etc). В документации написано, что для этого сейчас используется HTTP интерфейс и у вас есть готовые модули для этого.

Что хочется узнать
1) Планируется ли эти модули отдать в open source так же как и сам ClickHouse?
2) Планируется ли документировать TCP интерфейс, а то сейчас мы видим
Родной интерфейс используется в клиенте командной строки clickhouse-client, при межсерверном взаимодействии для распределённой обработки запроса, а также в программах на C++. Будет рассмотрен только клиент командной строки.


1) Планируется ли эти модули отдать в open source так же как и сам ClickHouse?

Не уверен. Например, для Python есть несколько разных модулей в виде простых обёрток над HTTP интерфейсом. Может быть, какой-то из них автор захочет выложить, пусть даже просто ради примера. Но они все не представляют большой ценности.

2) Планируется ли документировать TCP интерфейс, а то сейчас мы видим

Пока нет — TCP интерфейс и внутрений C++ интерфейс специально не документирован для того, чтобы не бояться ломать совместимость протокола и ABI. Поэтому, для внешних программ только HTTP интерфейс.
UFO just landed and posted this here
ClickHouse может быть использован в том числе, для вставки данных напрямую из того места, которое эти данные генерирует.
Источник должен самостоятельно собирать данные в некоторые не слишком частые batch-и (раз в секунду — нормально) и отправлять их INSERT-ом по HTTP.

ClickHouse позволяет вставлять данные сравнительно эффективно.
О 10 000 строк в секунду (как вы написали) можно вообще не беспокоиться.

Реальные величины — это, например, 100 000 строк в секунду, в рассчёте на один сервер, на один поток; каждая строка имеет размер ~ 1 КБ (если передавать в несжатом виде по сети, то это съест 1 Gbit), или, например, 500 000 строк в секунду, если строчки поменьше.

Подробнее.

Вы можете предположить, что INSERT работает неэффективно из-за использования HTTP и из-за передачи данных в текстовом формате. Рассмотрим масштаб проблемы.

HTTP chunked transfer encoding, это, по сути, один лишний memcpy. Допустим, 5 GB/sec на одно ядро. То есть, не тот масштаб, о котором имеет смысл беспокоиться при INSERT.

Передача данных в текстовом виде, это от 100 до 1000 MB/sec., в зависимости от того, насколько хорошо ваше приложение может записывать числа в текстовом виде и эскейпить строки. Видно, что масштаб соответствующий, и это может съесть до половины времени вашего приложения, если сериализация в текстовом виде реализована неэффективно. В этом случае, существует возможность использовать бинарный формат RowBinary. См. здесь.
UFO just landed and posted this here
Может быть стоит сделать описание протокола взаимодействия между клиентом и сервером, чтоб дать возможность разрабатывать сторонние клиенты?
Для сторонних клиентов проще всего использовать HTTP интерфейс. Например, API Яндекс.Метрики использует именно его для построения отчётов.
Да, jdbc драйвер необходим. Это реально блоккер для использования со всякими olap системами.
JDBC драйвер опубликовали: https://github.com/yandex/clickhouse-jdbc
Всё становится сложнее, если вам нужно выполнять запросы в интерактивном режиме по неагрегированным данным, поступающим в систему в реальном времени. Для решения этой задачи, открытых технологий подходящего качества до сих пор не существовало.


GreenPlum?
Спасибо! Стыдно сказать, я видел новость про open-source Greenplum и хотел изучить его подробнее, но потом забыл про это.
Надо будет уделить этому больше внимания. Возможно, утверждение «до сих пор не существовало» придётся пересмотреть.
Про Citus слышал, даже пробовал ставить для бенчмарков, но немного не хватило времени.
Исключительно ради экономии времени и никак не ради пиара, вот тут я вкратце описывал архитектуру Greenplum.
Большое спасибо за вывод в opensource, будем тестировать в наших реалиях :) Правда, очень нужен стабильный ODBC-драйвер…
А в чем проблема комментариев на русском языке, в свете рускоязычного проекта?
Я в текущем проекте тоже все комментирую на русском, более того коментарии к комитам тоже пишу на русском, т.к. читатели 100% русские.
Если ориентироваться только на русскоязычную аудиторию — нет проблем. Просто я предполагал, что проект такого уровня является достаточно значимым, чтобы публиковать его на весь мир.
Может быть изначально не предполагалось выкладывать в опен-сорс.
Может быть руки ещё до перевода не дошли.
Да, совершенно верно. Изначально у нас не было цели разработать open-source СУБД.
Я понимаю, что использование русского языка для комментариев — это минус для open-source продукта.

При этом к самому факту наличия подробных комментариев на русском языке следует отнестись позитивно: это лучше, чем если бы комментариев не было или если бы они были бы менее понятными для основных разработчиков.
Не вижу абсолютно никаких минусов в использовании русскоязычных комментариев в проекте, который изначально не создается под open source и активно используется в бизнес-задачах русскоязычной компании. И нет большого смысла заставлять разработчиков переводить свою мысль на английский в ущерб продуктивности отдельно взятой команды. Честно говоря, не припоминаю, чтобы где-либо в гайдлайнах встречал что-либо касательно требований к английскому языку в комментариях.
Если вас действительно это смущает, то сделайте пул-реквест. Это же теперь open source. :)
Почему ты думаешь, что если комментарии на русском — то нет гайдлайна?
Почему вас не смущает, что в космосе пишут на российских приборах на русском, даже работающие в международной станции? Китайцы тоже пишут на китайском. В своем языке нет ничего плохо и даже наоборот, так и надо делать — свой язык надо отстаивать.
>>, так и надо делать — свой язык надо отстаивать.

Опенсорс — место для коллаборации, но никак не до отстаивания языка.
Космос — тоже место для сотрудничества. И..?
Названия, например, «Союз», можно и на русском написать, но комментарии — это часть технической документации. Я сомневаюсь, что инструкции на МКС на русском.
Мало того, что на русском (как и многие обозначения на приборах), так еще и знание русского языка является обязательным требованием для работы на МКС.
ООН, признающая русский язык своим официальным (одним из шести) языком, немного не согласна с таким постулатом. Предвосхищая возможное возражение, что программистский мир — особая среда со своими традициями и канонами, отмечу, что мир может меняться, потому как не заспиртован ;-).
Насчет гайдлайнов — открыл указанный файлик и увидел:
IColumn & column = *res;

Честно признаюсь, что секунд 15 пытался понять, что тут хотел сделать автор, и сначала в голову пришло побитовое «и» между переменной ICoumn и column… Никогда не видел, чтобы ссылки так объявлялись, обычно либо «IColumn &column», либо «IColumn& column». Это точно читабельный вариант? Да и вообще как-то мой личный опыт был таков, что явно ссылки не так уж часто объявляются…
P.S. Я знаю C++ довольно хорошо, но на практике больше на C# программирую, поэтому может отвык уже, одичал :)

Странно, что нигде нет сравнения с Solr/ElasticSearch. Они тоже активно используются в качестве аналитических БД.

Это продукты немного другого профиля.
Насколько я понимаю, основная задача Solr/ElasticSearch — работа с полнотекстовым индексом.

В ClickHouse нет полнотекстового индекса.
Основной характер нагрузки состоит в том, чтобы достать по диапазону первичного ключа какое-то, возможно весьма большое множество строк, и как можно быстрее выполнить над ним нужные операции: отфильтровать, агрегировать и т. п. При этом, сам индекс — первичный ключ, устроен достаточно примитивно, зато всегда требует немного оперативки (даже при наличии триллионов строк в таблице на одном сервере) и поддерживает локальность расположения данных на диске — для того, чтобы читать искомое множество данных с минимальным количеством seek-ов.

Короче говоря, в одних задачах важнее по-умному достать из базы небольшое количество данных, а в других — как можно эффективнее прочитать и обработать достаточно большое подмножество данных.
Отнюдь, у Elasticsearch сейчас отличные возможности по фильтрации, агрегации и вообще работе с большими объёмами постоянно поступающих данных. Скорость, надёжность и удобство на высоте. Для любой аналитики — самое то, у них на сайте можно посмотреть, сколько огромных систем на нем построено. Полнотекстовый поиск там лишь одна из сотен функций.
Это хорошо.

Вы не возражаете, если у меня будет к вам маленькая просьба?
Надо взять тестовые данные из этой статьи, загрузить их в Elasticsearch, и прогнать те запросы, которые приведены в качестве примеров.
Мне будет очень интересно посмотреть, как всё будет работать!
Будет 3-4 часа на загрузку (на 2×E5-2630v3, 64Gb RAM, 2xSSD), но на запросы он должен по-шустрее clickhouse'а отвечать. Надо тестить… Но мы скорее будем на своих Едадиловских данных тестить clickhouse, потом с текущим эластиком сравнивать. Эластик на наши запросы, если данные на SSD или в оперативке, отвечает сравнимо с Druid'ом по скорости, не знаю как они это делают, ну не хранят агрегаты же? :-)

Про 3-4 часа на загрузку таких данных это вы загнули. Еще года 3 назад в моих экспериментах с ES 0.9x пара гигабайт XML-фидов превращалась в json и заливалась на одну ноду/индекс минут за 30ть, с сервером на HDD. В индексе при этом был полнотекстовый поиск с ngram'ами, вес индекса на выходе за 15GB. Сейчас все еще быстрее, а простые данные в простой индекс вообще грузятся близко к скорости самого SSD.

В чем загнул? Пара гигабайт против 60 гб тут. На вышеприведенном конфиге можно примерно на 15к/с рассчитывать. 150кк документов — 10000 секунд, почти 3 часа.

У меня были ngram'ы. Без них все эти 60Гб загрузятся за считанные минуты.
У ES есть nightly benchmarks, на не самых простых данных с гео он загружает по 80к документов в секунду. Это всего 35 минут для данного набора, а скорее всего будет раза в 3 меньше в силу его простой структуры.


Кстати, o6CuFl2Q, сколько ClickHouse требуется времени на загрузку тестового набора?

Сейчас проверил — получилось 25 мин. 24 сек. — это 109 336 строк в секунду.
Время включает разжатие xz и парсинг CSV (команда для загрузки — точно как написано в статье).
То есть ты не из практического опыта исходишь, а из бенчмарков версий которые даже не RC?) По бенчмаркам стабильных версий моя оценка справедлива. n-граммы добавят процентов 10-15% времени, но на этих данных они не нужны :-).

Не помню, чтобы мы на ты переходили. Предлагаю вам доказать справедливость оценки, сделанной на основании домыслов, и никчемность benchmarks, путем эксперимента.

А я не заметил ни одного повода общаться с тобой на вы. Твое предложение мне не интересно — моя оценка это то что у меня реально на серверах происходит, а твоя оценка полностью описывается твоей фразой:

> У меня нет ни лишнего времени, ни лишней сотни гигабайт на SSD, чтобы провести описанный эксперимент с ES. Буду рад, если вы это сделаете хотя бы с той парой запросов, что я написал. Ставлю 10 к 1, что ES будет быстрее раз в 5.

Не видел предмет разговора в жизни, а лезешь к взрослым дядькам с советами. Фу таким быть.

Взрослое быдло — все равно быдло.

Было бы интересно почему ты пришел к выводу, что я быдло, но не вижу смысла продолжать дискуссию, потому что ты ещё в предыдущих сообщениях успел доказать то что твое слово ничего не стоит, а мнение подкрепляется личными эмоциональными фантазиями.
Сравнивали ли вы производительность Druid с еластиком, если да, то какие получились результаты и почему выбрали еластик? И если будете тестить clickhouse, то расскажите общественности что у вас вышло.
Выбрали эластик многим причинам (низкий порог вхождения, функциональность, автогенерация схемы, и т.п.), druid пока только тестим, для своих задач он хорош.

Пока нужные для запросов индексы в эластике влезают в оперативку — скорость выполнения аггрегаций в ES сравнима с выполнением запросов в Druid (где-то может быть хуже на порядок, а где-то даже лучше, зависит от данных и от запросов). Если данные не входят в оперативку, но лежат на SSD — у ES всё становится на порядок медленнее, как деградирует Druid мы пока не тестили, но есть подозрение что у него дела будут лучше.

Druid хорош тем, что он хранит собственно только данные необходимые для построения аггрегаций по заранее заданным измерениям и метрикам, и делает это эффективно. Собственно он создан для OLAP, ничего большего чем эффективно строить агрегации с его помощью не сделать, да и не нужно. У ES гораздо больше оверхед на размер индексов, следовательно большой объем данных потребует большего количества железа.

В нашем кейс — есть возможность снизить объем данных в ES с 2-3Тб в месяц до 100Гб в месяц. А по тем данным, которые в ES заливать не будем — достаточно Druid.

Эластик нам скорее всего будет нужен даже если основной объем данных перельем в clickhouse, так как пока не совсем понятно сможем ли на clickhouse'е реализовать некоторые свои потребности. Основное — span-запросы, мы через них делаем behaviour-matching. Ну и в паре мест fulltext-индексы нам тоже нужны. Но как хранилище и возможность исполнять sql-like запросы над полными данными clickhouse для нас может стать панацеей :-).

Без проблем, например вот это отдаст сразу из каких городов отправляется больше рейсов и распределение времени задержки прилёта, по авиакомпаниям в одном запросе, да еще и наверняка быстрее:


{
  "aggs" : {
    "most_flights_from" : {
      "terms" : {
        "field" : "OriginCityName",
        "size" : 20
      }
    },
    "carriers" : {
      "terms" : {
        "field" : "Carrier",
        "size" : 0
      },
      "aggs" : {
        "avg_delays": {
          "percentiles": {
            "field" : "DepDelay"
          }
        }
      }
    }
  }
}

Это 2 простейших агрегации (terms и квантили), все остальное тоже легко выполнимо — в ES три десятка разных агрегаций, которые спокойно накладываются, вкладываются и поворачиваются как угодно.


Более того, ES умеет еще и сам находить "выделяющиеся из общей массы" значения, например по каждой авиакомпании подсказать город, из которого она летает заметно чаще остальных авиакомпаний. Это настолько сложно, что надо всего-лишь добавить в последний aggs перед/после avg_delays это:


        "significant_cities": {
            "significant_terms": {"field": "OriginCityName"}
        }

Я уж не говорю про невероятно удобную работу с датами и геолокацией — хочешь тебе агрегации и вычисления, хочешь — сортировка с экспоненциальным убыванием веса от расстояния, при этом, например, ближе 300м вес одинаковый, дальше 3км вообще всем ноль. Берите дистрибутив и пробуйте, документация там более чем понятная. ES очень активно используют Github, Foursquare, Twitter, Netflix и многие другие, вплоть до Cisco с Microsoft. Свой велосипед можете выбросить.


P.S. Если что — я как раз недавно написал систему аналитики форм, использующую ES и одним запросом считающую 2 десятка показателей вроде квантилей среднего времени, потраченного на каждое поле, % юзеров, взаимодействовавших/менявших это поле, средней длины вводимого в поле текста и т.д. Все это с группировкой/фильтрацией по чему угодно — хоть по ОС или урлу, хоть по css-классу формы (и дате, естественно). В базе сырые данные — события (click, focusin, change и т.д.) и время, десятки миллионов записей и 0.5GB данных для одного небольшого сайта, на котором все это обкатывается. Уровень вложенности агрегаций уходит за 10, все крутится на маленьком запасном сервере с HDD(!) и отдает все два десятка показателей с двойной группировкой и любой фильтрацией за 1 секунду уже в виде HTML. Если сильно интересно — могу дать посмотреть. С вашей штукой это превратилось бы в 30 отдельных запросов с кучей подзапросов и структуру данных из 3-4х таблиц, которые надо постоянно join'ить. Про скорость даже боюсь думать :)

Это весьма круто!
Спасибо за примеры.

одним запросом считающую 2 десятка показателей вроде квантилей среднего времени, потраченного на каждое поле, % юзеров, взаимодействовавших/менявших это поле, средней длины вводимого в поле текста и т.д. Все это с группировкой/фильтрацией по чему угодно — хоть по ОС или урлу, хоть по css-классу формы (и дате, естественно). В базе сырые данные — события (click, focusin, change и т.д.) и время

Вы прямо описываете sweet-spot сценарий для ClickHouse :)

все крутится на маленьком запасном сервере с HDD(!)

0.5 GB данных помещаются в page cache и поэтому запросы не должны упираться в дисковую подсистему.

С вашей штукой это превратилось бы в 30 отдельных запросов с кучей подзапросов и структуру данных из 3-4х таблиц, которые надо постоянно join'ить.

А может и не превратилось бы. Предположительно, будет одна «big flat table» с исходными событиями, и один или несколько запросов со всеми нужными агрегатными функциями. Возможно, с использованием такой функциональности.
На 10 млн. строк вряд ли время выполнения составит больше секунды.
Вы прямо описываете sweet-spot сценарий для ClickHouse :)


Schema-less была обязательным условием, так что ClickHouse точно нет :)
0.5 GB данных помещаются в page cache и поэтому запросы не должны упираться в дисковую подсистему.


На этом сервере еще всякая фигня крутится, но да, может быть такой эффект. Тем не менее я еще на старых версиях ES экспериментировал с индексами размером в десятки GB и куда более простыми запросами (полнотекстовый поиск + 2-3 параметра) — ответ всегда укладывался в десятки миллисекунд.
Предположительно, будет одна «big flat table» с исходными событиями, и один или несколько запросов со всеми нужными агрегатными функциями.


Событие (event) относится к input'у, тот в свою очередь принадлежит form, которая относится к pageview. На один pageview, естественно, может быть несколько форм, сотни инпутов и десятки тысяч событий. Агрегация идет на всех уровнях — и по событиям, и по инпутам/их типам, и по формам, и по pageview. big flat точно не вариант, было бы огромное дублирование.

В случае с ES это один schema-less документ — pageview, в котором все вложено, и делать с ним можно все, что угодно — например посчитать общее число submit'ов отдельно для каждого встречающегося класса формы для pageview с OS = Windows и форм с action = /book, сортировка по количеству pageview для каждого класса формы. Занимает это строчек 20 и считается попутно со всем остальным. Попробуйте здесь такой же запрос для ClickHouse нарисовать ;)
Если всё работает со schema-less данными, то это отлично.
Schema-less не подходит, если необходимо любой ценой максимизировать скорость сканирования данных.
Это различие примерно аналогично различию между статической и динамической типизацией.

Для примера, ClickHouse может на простых запросах обрабатывать более миллиарда строк в секунду на одном сервере. А скорость в несколько сотен миллионов строк в секунду видна даже на примерах из этой статьи. И это вряд ли возможно со schema-less данными.

big flat точно не вариант, было бы огромное дублирование

Как ни странно, это как раз может быть нормальным. Дело в том, что повторяющиеся значения хорошо сожмутся. Хотя имеет смысл сделать несколько таблиц, но в самой детальной (events) дублировать столбцы из input, form и т. п.

Для примера, в данных Метрики, столбец Title — заголовок страницы — может очень часто повторяться для одного сайта (при этом он занимает в среднем 94 байта в несжатом виде). Но хранить Title inplace в таблице гораздо лучше, чем пытаться сохранить уникальные Title в отдельной таблице и делать сложный JOIN.
Schema-less не подходит, если необходимо любой ценой максимизировать скорость сканирования данных.
Это различие примерно аналогично различию между статической и динамической типизацией.


Мне кажется вы плохо понимаете, как устроен ES. Schema-less отнюдь не значит, что данных хранятся абы как и их структура каждый раз вычисляется заново.
In Elasticsearch, all data in every field is indexed by default. That is, every field has a dedicated inverted index for fast retrieval. And, unlike most other databases, it can use all of those inverted indices in the same query, to return results at breathtaking speed.


У меня нет ни лишнего времени, ни лишней сотни гигабайт на SSD, чтобы провести описанный эксперимент с ES. Буду рад, если вы это сделаете хотя бы с той парой запросов, что я написал. Ставлю 10 к 1, что ES будет быстрее раз в 5.
Но хранить Title inplace в таблице гораздо лучше, чем пытаться сохранить уникальные Title в отдельной таблице и делать сложный JOIN.


Вот тут то и чувствуется вся сила и удобство ES, ибо там этот геморрой вообще не нужен. Сжатие сжатием, но оверхэд в сотни процентов у вас все равно будет. А если вдруг понадобится достать еще одно поле, которое изначально не продублировали — лучше сразу застрелиться.
У меня нет ни лишнего времени, ни лишней сотни гигабайт на SSD, чтобы провести описанный эксперимент с ES. Буду рад, если вы это сделаете хотя бы с той парой запросов, что я написал. Ставлю 10 к 1, что ES будет быстрее раз в 5.

Надо попробовать, если удастся найти время.

In Elasticsearch, all data in every field is indexed by default.

В этом случае будет проблемой размер индексов.
Это нужно считать. Часто для данных в ClickHouse средний размер строки в сжатом виде получается очень маленьким. При среднем размере строки в десятки байт, размер индекса становится проблемой.

В ClickHouse для уменьшения объёма, специально используется «разреженный» индекс — он не позволяет найти, где расположена конкретная строчка, а позволяет найти только начало диапазона из index_granularity строк (рекомендуется 8192 для почти всех приложений). То есть, при чтении будет читаться немного лишних данных, зато индекс будет занимать примерно нулевое количество места по сравнению с объёмом данных.
С одной оговоркой: field is indexed by default, но это отключаемо. В маппинге полю можно проставить параметр
index: "no"

Это, конечно, в случае, если известны все возможные поля, но не при абсолютном анархичном schema-less.
С помощью dynamic templates можно отключить индексацию для всех не заданных полей или по шаблону — https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html.

Но какой смысл в эластике, если не индексировать поля? Как хранилище он не эффективен, проще монгу взять.
Но какой смысл в эластике, если не индексировать поля? Как хранилище он не эффективен, проще монгу взять.

На основе какого опыта вы пришли к такому выводу?
Работаю активно с данным инструментарием(и с mongodb, и c elasticsearch) каждый день на достаточно больших данных и выводы могу сделать противоположные вашим.
Динамика данных: ~3.5млрд активных записей, средний размер 3КБ, с ежедневным замещением ~110млн (поступление новых, удаление старых). И на таких объемах у меня получилось следующее:
* монга хороша для очень быстрого доступа к данным (в том числе холодным), в этом плане она сильно выигрывает у эластика, и лучше держит резкие всплески нагрузки.
* эластик хорош для агрегации (она функциональнее и быстрее, нежели у монги), сэмпловой выборки по всем данным, а также для выполнения сложных запросов — делает это гораздо быстрее монги.

Основное, в чем эластик менее эффективен относительно монги — это объем хранимых данных и объем индексов, но, взвешивая профит работы с данными, по большинству критериев выигрывает эластик.
> монга хороша для очень быстрого доступа к данным (в том числе холодным), в этом плане она сильно выигрывает у эластика

> Основное, в чем эластик менее эффективен относительно монги — это объем хранимых данных и объем индексов

Я собственно это и имею ввиду. Опыт — построение сложных отчетов, когда агрегаций ES не достаточно и приходится выгружать миллионы документов в Python. Иногда эффективнее в hadoop'е по сырым сжатым данным пройтись, чем из эластика их достать. Выгрузка данных в JSON по HTTP из эластика сильно проигрывает выгрузке BSON по бинарному протоколу монги.

В текущем кейсе у меня таких выборок не много, ES — нормально, он в основном для агрегаций используется. Хотя иногда приходится выгрузки делать, и это боль. А на прошлом месте работы был вполне успешный опыт подобных выгрузок с монгой.

> взвешивая профит работы с данными, по большинству критериев выигрывает эластик

Согласен, в нашем кейсе для аналитики ES тоже лучше монги :-).

Но если данные не индексировать, то зачем их хранить в ES?.. Выборки по ним делать нельзя. Если для того чтобы просто доставать — лучше монгу взять.

Отдельный вопрос — поля метрик. Не знаю, влияет ли отключение их индексирования на производительность аггрегаций по ним? Какие-то агрегаты для индексов насчитываются, что будет если для метрик выключить индексирование? Да и иногда по метрикам тоже выборки хочется делать.
Но если данные не индексировать, то зачем их хранить в ES?.. Выборки по ним делать нельзя. Если для того чтобы просто доставать — лучше монгу взять.

В этом случае идея заключается в другом: часть полей индексируется, по которым проходит агрегация и сама критерия при запросе, а некоторые поля — это данные, которые нужно получить в довесок. Вы ведь в базе данных тоже индексы не на все поля создаёте.

Отдельный вопрос — поля метрик. Не знаю, влияет ли отключение их индексирования на производительность аггрегаций по ним? Какие-то агрегаты для индексов насчитываются, что будет если для метрик выключить индексирование? Да и иногда по метрикам тоже выборки хочется делать.

К сожалению или к счастью не приходилось с этим сталкиваться, да и более интересных экспериментов и ресёрча хватает. Но если я правильно вас понял, то метрики — это в основном числовые значения. Почему вы их не индексируете? Они не так уж много места занимают.
> а некоторые поля — это данные, которые нужно получить в довесок

Кажется в случае elasticsearch таких полей обычно не много. А изначально мое замечание было про отключение индексации для всех полей. Хотя сейчас я уже понял что это вполне нормальная ситуация для стандартного сценария использования ES для full-text поиска — с одним analyzed полем, и набором не индексируемых полей данных, разным для разных документов, которые просто удобно сразу получать в результатах поиска.

> метрики — это в основном числовые значения. Почему вы их не индексируете? Они не так уж много места занимают.

Я не говорил что не индексирую метрики, просто отметил как отдельный случай в котором может быть допустимо выключить индекс.

Подскажите, есть ли возможность в Elasticsearch сделать join по нескольких таблицам с возможностью сортировки по полям?
Пример: есть 2 таблицы — авторы и посты с лайками. Необходимо вывести информацию про авторов, отсортированную по суммарному количеству лайков в постах данного автора. Можно ли это сделать в один запрос?

Конечно можно. В ES нет понятия таблиц, там индексы и документы. Сортировать их можно как угодно, хоть наизнанку — сами лайки по числу постов у автора. В доках как раз пример про посты, не поленитесь. В вашем случае автор и пост будут связаны как parent-child, а лайки можно просто вкладывать в пост. У нас заведения, например, сортируются в т.ч. (но не только, там целая формула) по числу подтвержденных броней за последние 2 месяца, все это внутри одного запроса.

Не нужно использовать Elasticsearch как замену RDBMS, join'ы через parent-child там сделаны весьма спорно — весь словарь связей parent-child всегда хранится в памяти, целиком. Плюс с шардированием есть ньюансы.

Если говорить про аналитику, то в OLAP-топологии звезда Elasticsearch применим. Но в общем случае, хотите реляционку — возьмите реляционку.
> parent-child всегда хранится в памяти, целиком

Оказывается не совсем правда уже, но в любом случае вот правильный линк который необходимо прочитать при возникновении желания поделать JOIN'ы в ES — https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-performance.html.
Хотелось бы какую-либо информацию о минимальных ТТХ серверного юнита для запуска ClickHouse.
(документацию покурил, не нашёл, может мало курил)
очень хорошие разумные современные рецепты. Немного отличается от видеостриминга, но про своп аж тронуло.
Как вам идея написать небольшой пост по выбору и настройке железа/ОС для систем аналитики?) Эти советы не только для ClickHouse актуальны :-).
Спасибо за предложение! Сильно сомневаюсь, что получится написать в ближайшее время.
Алексей! Спасибо Вам за такой грандиозный и ооочень нужный проект!
Яндекс! Спасибо за возможность пользоваться!
Документация\референс просто замечательный! Автор со всей любовью и профессиональным пониманием вопроса подошел к вопросу документации. Такое редко в каком проекте встретишь, и что бы было професионально все разложено по полочкам, и понятно, и читать просто приятно (на одном дыхании прочитал)! И еще бенчарки в придачу!!!

Алексей, Вам надо проект как то в массы продвигать, на конфы, статьи в english сообществах и ресурсах. Взять хотябы в качестве примера ребят из Mail.ru с их Tarantool.

Я надеюсь и хочу верить, что данный проект найдет широкий отклик у коммюнити и поможет многои и многим другим интерстным проектам :)
Светлого будущего проекту!!!
Будет!
Сейчас приняли пулл-реквест с примерными Dockerfile'ами. Немного разберемся с версионированием и выложим на hub.docker.com/r/yandex.

Для теста хватит, если в бой — всё равно переписывать.
Ждём оффициального образа :)

Выпустили:
https://hub.docker.com/r/yandex/clickhouse-server/ — образ сервера
https://hub.docker.com/r/yandex/clickhouse-client/ — образ клиента
Добрый день. Можно вкратце и, желательно, популярно описать как он работает?

Скорости впечатляют, но чудес же не бывает.
Спасибо.
Коротко это описано в самом начале документации.

Основа для скорости — это хранение данных по столбцам и векторный движок. По этим признакам, система не отличается, например, от Actian Vector (бывшая Vectorwise), которая может похвастаться сравнимой скоростью обработки запросов.

Дополнительные преимущества в производительности достигаются за счёт:
— алгоритмической оптимизации;
— низкоуровневой оптимизации;
— специализации и проработки частных случаев.
Мне резануло название «столбцовая СУБД».

Разве не «колоночная СУБД»? Или есть разница, которую я не уловил?

Терминология («колоночная СУБД») встречается довольно часто, https://special.habrahabr.ru/kyocera/p/95181/, например.
Действительно, чаще говорят «колоночная».
Почему-то у нас закрепилось именно выражение «столбцовая». Как-то приятнее произносить.
Никакой разницы нет.
Мне кажется, вы немного поспешили с анонсом. Не хватает содержимого сабмодуля private:

https://github.com/yandex/ClickHouse/blob/master/.gitmodules

[submodule "private"]
path = private
url = git@github.yandex-team.ru:Metrika/ClickHouse_private.git


… и простым смертным его нельзя склонировать:

git clone git@github.yandex-team.ru:Metrika/ClickHouse_private.git
Cloning into 'ClickHouse_private'...
ssh: connect to host github.yandex-team.ru port 22: Network is unreachable
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.


В CMakeLists.txt этот сабмодуль числится как зависимость, без него ничего не соберется:

add_subdirectory (private)
Так как вы не можете скачать этот сабмодуль, у вас будет пустая директория private.
При этом, всё собирается нормально, так как у всех собираемых программ нет зависимости от содержимого private.
Упоминание пустой директории в CMakeLists тоже нормально работает.

Если нет — можете указать версию CMake и привести пример, как он не работает.
Оригинальное решение. Я, видимо, пожалею, что спросил, но — а зачем так сделано? :)
Серьёзных причин делать именно так нет, но так оказалось довольно просто.
Яндекс, спасибо!
Сколько же аналитических МРР-систем вышло в Open-Source в последнее время!
В начале статьи вы не совсем правильно провели аналитику рынка, разделив его на 5 сегментов и противопоставив себя каждому.
Все перечисленные решения в сравнении плюс/минус тоже самое(кроме платных).
Геораспределенность в аналитической системе? зачем? «Надстройки над Hadoop» это полноценные аналитические МРР-системы и от вашего решения отличаются практически ничем, умеют делать такие же SQL запросы, имеют почти такое же колоночное хранилище, с сжатием. Приближенные вычисления — интересно.
Я не знаю конечно какие цели были у Яндекса, но конкурировать будет с кем.
А вы не думали сделать аналог BigQuery на его основе? Мне кажется было бы интересно, тем более у вас имеются преимущества.
Геораспределённость нужна нам для обеспечения аптайма Яндекс.Метрики при недоступности датацентра. Особенно в связи с «учениями».

Все перечисленные решения в сравнении плюс/минус тоже самое(кроме платных).

В общих чертах, наверное, так и есть. Но если рассматривать детали, то будут видны тысячи отличий, многие из которых очень важны.
Для примера, некоторые системы не переупорядочивает данные постоянно по мере вставки. Вы не сможете одновременно постоянно загружать туда данные и эффективно доставать данные по диапазону первичного ключа. Но если для вас достаточно один раз загрузить данные, а затем все запросы сводятся к full scan, то это нормально.

А вы не думали сделать аналог BigQuery на его основе? Мне кажется было бы интересно, тем более у вас имеются преимущества.

Не могу сказать.
Пока нет, не планируем.

Так как у нас никто не использует Windows, обеспечить поддержку (автосборку, функциональные тесты, тесты производительности) под эту платформу нам довольно сложно.
поясните, пожалуйста: речь идет о хранении сырых данных, но без индексов вообще?
Данные можно назвать сырыми, но не совсем.
В Метрике, в ClickHouse сохраняются неагрегированные (одна строка в базе — одно событие), но «чистые» и «обогащённые» данные.
То есть, перед загрузкой в ClickHouse, данные слегка обрабатываются (например, декодируются URL-ы); вычисляется и раскладывается в отдельные столбцы всё, что можно вычислить: поисковый запрос, регион, браузер и т. п.

Данные хранятся в таблице с первичным ключом.

Например, сейчас у нас в таблице hits, 8.2 триллиона строк. При каждой загрузке отчёта в интерфейсе Метрики (~2 млн. раз в сутки), делается запрос в ClickHouse. Ясно, что мы не могли бы показывать отчёты, если бы в таблице не было ключа.

Первичный ключ в таблицах Метрики начинается на идентификатор счётчика — то есть, клиента Метрики. Это позволяет быстро доставать данные по одному или по множеству счётчиков для отчёта.

При этом, также есть возможность выполнять глобальные запросы — по всем счётчикам сразу.
Для примера, запрос типа такого
SELECT CounterID, count() FROM hits_all WHERE EventDate = today() GROUP BY CounterID ORDER BY count() DESC LIMIT 20

Выполняется на кластере с такой скоростью:
20 rows in set. Elapsed: 0.815 sec. Processed 12.13 billion rows, 72.77 GB (14.87 billion rows/s., 89.25 GB/s.)
(~2 млн. раз в сутки) — какое железо и сколько? Если не секрет :)
23 запросов в секунду, так то можно и посгрю натюнить даже для больших данных )
Я просто пытаюсь понять чем это лучше Hive, ES, кластер посгри. Так что не воспринимай как тролинг )
Железо всё-таки секрет.

23 запросов в секунду, так то можно и посгрю натюнить даже для больших данных )

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

Если мы вдруг выясним, что можем обрабатывать запросы в два раза быстрее, то мы вместо этого предпочтём увеличить порог для срабатывания сэмплирования в Метрике — то есть увеличить объём данных для обработки и качество сервиса для пользователей.
Я это все к чему, я представляю структуру select'ов + join|unio для ваших отчетов (с учетом семплирование), она достаточно фиксированная.
Вот почему pg cluster привожу как пример, если не делать прям совсем кастом-кастом по любым датам и диапазонам то, интуитивно, такой rps получить можно, при всех прочих равных.
Короче, заинтересовали, буду щупать :)
я не понял насчёт вторичных ключей: надо ли (и можно ли) их строить по таблице?
Их нет (точней только фиксированый опциональный Date и только secondary), только через избыточность либо full scan.
'Performance comparison of analytical DBMS' — а на каких конфигурациях (железо, оси) проводились тесты?
И правильно ли я понял: *MergeTree не поддерживает доп. индексы (точней только secondary Date)?
Я кстати не понял в чем радикальное отличие от Hive (если не считать скорости). Кстати как-то тюнили Hive или голый взяли?
Да и ваш map reduce ограничен оперативкой, верно я понял?
PS если способ хранения данных откинуть
а на каких конфигурациях (железо, оси) проводились тесты?

Железо такое: двухсокетный E5-2650 v2, 128 GiB RAM, RAID-5 из 8 дисков SATA 7200 RPM на 6 ТБ.
ОС — Ubuntu 14.04.

И правильно ли я понял: *MergeTree не поддерживает доп. индексы (точней только secondary Date)?

Да, правильно. Для этого есть причины.

Пусть у нас есть индекс, и, при обработке запроса, согласно этому индексу, необходимо прочитать из таблицы множество данных по некоторому множеству смещений. Если множество достаточно большое (например, хотя бы от 1000 записей), и если данные не помещаются в оперативку, то при использовании HDD, скорость чтения этого множества будет определяться локальностью его расположения на диске. Если множество расположено не локально, то для его чтения, придётся выполнить примерно столько seek-ов, сколько элементов есть во множестве. Обычно это говорит о том, что если данные расположены недостаточно локально, то аналитические запросы не будут работать с приемлимой скоростью. Подробнее об этом рассказывалось в предыдущей статье.

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

Поэтому, локальность по нескольким индексам, если она нужна, имеет смысл достигать путём дублирования данных. Например, так устроены проекции в Vertica.

Пример, когда это необходимо — рекламная сеть, в которой есть рекламодатели и рекламные площадки. Одна рекламная кампания может откручиваться на многих площадках, а одна площадка может показывать рекламу от многих рекламодателей. Если мы хотим сделать сервис с отчётами и для рекламодателей и для площадок, то имеет смысл хранить одни и те же данные в двух таблицах с разными первичными ключами.

Я кстати не понял в чем радикальное отличие от Hive (если не считать скорости). Кстати как-то тюнили Hive или голый взяли?

Не тюнили. Более того, у нас тестировался довольно старый Hive, надо будет обновить.
Главное отличие — ClickHouse подходит для «онлайн» запросов из веб-интерфейса. То есть, скорость выполнения запросов позволяет выполнять запросы прямо в момент загрузки страницы с отчётом. Трудно представить себе сервис, в котором при каждом переходе между страницами, пользователь должен ждать выполнения запроса в Hive.

Да и ваш map reduce ограничен оперативкой, верно я понял?

Недавно была добавлена возможность внешней агрегации — с сохранением временных данных на диск. Эта возможность ещё не документирована.
Недавно была добавлена возможность внешней агрегации — с сохранением временных данных на диск. Эта возможность ещё не документирована.

Интересно! Жду доки, будет интересно огромную выборку попробовать.

Не тюнили. Более того, у нас тестировался довольно старый Hive, надо будет обновить.
Главное отличие — ClickHouse подходит для «онлайн» запросов из веб-интерфейса. То есть, скорость выполнения запросов позволяет выполнять запросы прямо в момент загрузки страницы с отчётом. Трудно представить себе сервис, в котором при каждом переходе между страницами, пользователь должен ждать выполнения запроса в Hive.

Вроде скоро из инкубатора выйдут новые проекты, ранее упоминали.
В hive'е добиться online можно, кешированием (горячие данные), hive (холодные), конечно доля online теряется, но и у вас не прям онлайн. Пока данные от счетчиков придут, пока зальется в кластер… это все латенси. Это я к чему, к тому что латенси в систему будет всегда.
Да, правильно. Для этого есть причины.
...

Отчасти согласен, можно по дискутировать )
Но, замечу, по опыту, избыточность может привести к куда более страшные последствиям.
К примеру, консистентность данных при связи один к многим нельзя гарантировать. Тригеров я у вас не нашел, что означает, все на совести разработчика.
Кстати, говоря о консистентность, а какой уровень изоляции транзакции? И есть ли какие-то известные проблемы c network partition?
И есть ли какие-то известные проблемы c network partition?

При использовании ReplicatedMergeTree, в случае network partition, INSERT работает только в той части сети, из которой доступен кворум ZooKeeper. SELECT работает в обеих частях сети, но в одной из них будет возвращать устаревшие данные.

Обычно это означает, что при отключении от сети одного датацентра, в этом датацентре не будут записываться данные. В случае сценария использования для веб-аналитики это нормально, так как в этот датацентр не будут также поступать исходные данные (логи) из внешней сети, и записывать при этом нечего.

Кстати, говоря о консистентность, а какой уровень изоляции транзакции?

Транзакции не поддерживаются.
Запрос INSERT вставляет данные по блокам (не более 1 048 576 строк по-умолчанию). Вставка каждого блока атомарна.
(В случае таблиц семейства -MergeTree), запрос SELECT использует для выполнения snapshot данных, который захватывается на момент начала выполнения запроса.
при использовании HDD, скорость чтения этого множества будет определяться локальностью его расположения на диске. Если множество расположено не локально, то для его чтения, придётся выполнить примерно столько seek-ов, сколько элементов есть во множестве.

Сейчас понятия «локальность на диске» и «количество seek-ов» стали довольно эфемерными с учетом того, что в продакшене мы имеем RAID-ы, SAN-ы, SSD-кэши, «умное» железо, «умные» ФС и т.п., часто в комбинации. Ваши алгоритмы в ClickHouse как-то пытаются это учитывать? Или же целиком полагаются на то, что близкое смещение в файле обеспечит достаточно хорошую физическую локальность?
Еще такой вопрос, а нет ли у вас готового образа, ansible или чего-то такого чтобы я мог залить в AWS? Или только мне надо накатить ubuntu 14.* и поставить dep пакет?
Готового образа нет.
Но на Ubuntu 14.04 всё нормально ставиться несколькими командами, как в статье. В том числе, проверял на Amazon-е.
оке, в выходные пощупаю )
Все же, подумайте сделать образы, docker, ansible и т.п. — сегодня это user friendly)
Про docker-образ написал выше. Совсем скоро будет (:
>Карта кликов в Яндекс.Метрике и соответствующий запрос в ClickHouse
А можно посмотреть на результат исполнения запроса?
Вы могли бы получить эти же данные по-другому: зайти на демо-счётчик в Метрике, открыть карту кликов; в браузере в отладчике открыть вкладку «сеть» и посмотреть, какие данные придут.

Результат
:) SELECT EventDate, Path, X, Y, T FROM mouse_clicks_layer SAMPLE 32768 WHERE CounterID = 29761725 AND URLNormalizedHash = 11352313218531117537 AND EventDate >= '2016-05-28' AND EventDate <= '2016-06-03' LIMIT 50

SELECT 
    EventDate, 
    Path, 
    X, 
    Y, 
    T
FROM mouse_clicks_layer
SAMPLE 32768
WHERE (CounterID = 29761725) AND (URLNormalizedHash = 11352313218531117537) AND (EventDate >= '2016-05-28') AND (EventDate <= '2016-06-03')
LIMIT 50

┌──EventDate─┬─Path───────────────┬─────X─┬─────Y─┬────T─┐
│ 2016-05-28 │ ?                  │ 15420 │ 32767 │   56 │
│ 2016-05-28 │ WA4AAAA1           │ 42802 │ 36408 │   73 │
│ 2016-05-28 │ ;A2AA4AAAA1        │ 29285 │ 56797 │   93 │
│ 2016-05-28 │ ;AAAA1AAA          │ 28086 │ 26623 │   33 │
│ 2016-05-28 │ ?                  │ 23130 │ 43007 │   19 │
│ 2016-05-28 │ ;A2AAAA1           │  4437 │ 35194 │  111 │
│ 2016-05-28 │ ;AAA3AAAAA1AA1     │ 26214 │ 26214 │  107 │
│ 2016-05-28 │ WA3AAAAA1AA1       │ 24341 │ 30246 │   91 │
│ 2016-05-28 │ ;A2AAAAA1AA1       │ 22469 │ 37808 │   44 │
│ 2016-05-28 │ ;AAA2AAAAA1AA1     │ 13107 │ 28398 │   35 │
│ 2016-05-28 │ A;A2AAAAA1AA1      │ 36044 │ 35388 │   25 │
│ 2016-05-28 │ WA5AAAAA1AA1       │ 18022 │ 31507 │   28 │
│ 2016-05-28 │ ;A3AA4AAAAA1AA1    │ 20830 │  4369 │   62 │
│ 2016-05-28 │ WA4AAAAA1AA1       │ 20596 │ 32767 │   47 │
│ 2016-05-28 │ PWWFA1AA1AAA       │ 18766 │ 45196 │   52 │
│ 2016-05-28 │ ?FA1AA1AAA         │ 38228 │ 10239 │  227 │
│ 2016-05-28 │ ;A1AAAAA1AA1       │ 37214 │ 23945 │  203 │
│ 2016-05-28 │ ;A1AAAAA1AA1       │ 25043 │ 49151 │   49 │
│ 2016-05-28 │ ;A1AAAAA1AA1       │ 15915 │ 21424 │   45 │
│ 2016-05-28 │ AA2AA1             │ 31302 │ 47645 │  163 │
│ 2016-05-28 │ WA3AAAAA1AA1       │ 22469 │ 26466 │   40 │
│ 2016-05-28 │ WA3AA3AAAAA1AA1    │ 32533 │ 13107 │   66 │
│ 2016-05-28 │ ;AAA3AAAAA1AA1     │ 35342 │ 45874 │   86 │
│ 2016-05-28 │ Qd1A1AA2AA1        │ 11179 │ 29490 │   98 │
│ 2016-05-28 │ ;A10AAAAA1AA1      │ 22703 │ 49151 │ 1068 │
│ 2016-05-28 │ WA5AAAAA1AA1       │ 38852 │ 24904 │   74 │
│ 2016-05-28 │ ;A2AA5AAAAA1AA1    │ 17085 │ 22366 │  158 │
│ 2016-05-28 │ AWA5AAAAA1AA1      │ 32767 │ 45874 │   81 │
│ 2016-05-28 │ A;A2AAAAA1AA1      │ 32767 │ 58981 │  135 │
│ 2016-05-28 │ AWA5AAAAA1AA1      │ 32767 │ 38010 │   66 │
│ 2016-05-28 │ AWA4AAAAA1AA1      │ 16383 │ 39321 │   96 │
│ 2016-05-28 │ AWA4AAAAA1AA1      │ 26214 │ 49151 │  112 │
│ 2016-05-28 │ A;A2AAAAA1AA1      │ 32767 │ 43253 │  122 │
│ 2016-05-28 │ AWA5AAAAA1AA1      │ 26214 │ 38010 │  150 │
│ 2016-05-28 │ AWA5AAAAA1AA1      │ 40631 │ 29490 │  172 │
│ 2016-05-28 │ AWA4AAAAA1AA1      │ 52428 │ 43253 │  178 │
│ 2016-05-28 │ A;A3AA4AAAAA1AA1   │ 36044 │ 50243 │  190 │
│ 2016-05-28 │ ;A8AA3AA4AAAAA1AA1 │ 10586 │ 23830 │  213 │
│ 2016-05-28 │ ;SA2AA2AA1         │ 52123 │ 23130 │   10 │
│ 2016-05-28 │ ;SA2AA2AA1         │ 53861 │ 30840 │   11 │
│ 2016-05-28 │ ;A2AAAAA1AA1       │ 31597 │ 35288 │   14 │
│ 2016-05-28 │ ;A7AA7AAAAA1AA1    │     0 │     0 │  722 │
│ 2016-05-28 │ ;Qd1A1AA2AA1       │ 16920 │ 10922 │ 1650 │
│ 2016-05-28 │ ;AAA2AA1           │ 55295 │ 43007 │  798 │
│ 2016-05-28 │ ;AAA2AA1           │ 40959 │ 36863 │  503 │
│ 2016-05-28 │ ;S3A2AA2AA1        │ 38859 │ 36408 │  275 │
│ 2016-05-28 │ ;AAA2AA1           │ 34815 │ 22527 │  133 │
│ 2016-05-28 │ ;A1AAAAA1AA1       │ 31831 │ 36548 │  112 │
│ 2016-05-28 │ dA2AA2AA1          │ 39648 │ 51881 │  903 │
│ 2016-05-28 │ WA4AAAAA1AA1       │  8659 │ 37808 │ 4198 │
└────────────┴────────────────────┴───────┴───────┴──────┘

50 rows in set. Elapsed: 0.032 sec.



Рассказывать, что это за строки (помогать разбирать работу счётчика Метрики) не буду.
Конечно, мог бы, если б знал. Теперь могу и знаю, спасибо!
Вы можете использовать сжатие при передаче данных. Формат сжатых данных нестандартный, и вам придётся использовать для работы с ним специальную программу compressor (sudo apt-get install compressor-metrika-yandex).

Строка из документации. Но такого пакета в репозитории нет. Где можно ознакомиться с форматом?
Этот пакет ещё не выложили (постараемся добавить). Можно собрать программу самому — программа расположена здесь.

На самом деле, документация в этом месте чуть-чуть устарела, так как у нас есть поддержка обычного HTTP сжатия (gzip/deflate через заголовки Accept-Encoding при чтении и Content-Encoding при отправке).

Как её включить, написано в примере здесь.

Единственная особенность — необходимость выставить параметр enable_http_compression в 1.
Это сделано для того, чтобы готовые HTTP клиенты не стали непреднамеренно использовать сжатие, которое может привести к повышенному потреблению CPU.

Также, при запросе можно указать настройку http_zlib_compression_level. По-умолчанию — 3.

Стоит иметь ввиду, что gzip сжимает медленно (на тесте time curl -sS 'http://localhost:8123/' -H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 10000000' | gzip -d | wc -c; получается всего 39 MB/sec.)
Спасибо!
Есть ли интеграция с какой-либо готовой системой визуализации типа Graphite?
У нас внутри ClickHouse используется в качестве бэкенда к Graphite.

Для интеграции требуется отдельный код (патч для Graphite для чтения данных из ClickHouse; сервер для записи данных в ClickHouse пачками; для поиска имён метрик по шаблонам), который не выложен. Когда и как его выкладывать, будут решать авторы кода и их руководители, поэтому я пока ничего сказать не могу.

В самом ClickHouse есть domain-specific функциональность для поддержки Graphite — это GraphiteMergeTree. Посмотреть, что она делает, можно в исходниках.

Наверное, пока не выложена вся остальная «обвязка» над Graphite, самому пользоваться этим не стоит.
А как в ClickHouse обработать такие кейсы:
  1. Авто-удаление исторических данных, скажем старше N дней (скажем 45 дней), как я понимаю в MergeTree данные партициируются за месяц и простого варианта нет? Или же создавать, таблицы одну на N дней и объединять их через MERGE и читать данные через неё, а если данные устарели удалять физические таблицы?
  2. Как быть, если в результате нужны все столбцы (строки из исходного лога)? Заводить отдельную колонку и хранить в ней строку лога без обработки?
2) SELECT *, но будет крайне затратно по диску.
Авто-удаление исторических данных, скажем старше N дней (скажем 45 дней), как я понимаю в MergeTree данные партициируются за месяц и простого варианта нет? Или же создавать, таблицы одну на N дней и объединять их через MERGE и читать данные через неё, а если данные устарели удалять физические таблицы?

Да, простое удаление только по месяцам. Мы хотим когда-нибудь сделать custom-партиционирование.
По одной таблице на день — тоже вариант (у нас такое используется для одной задачи), но не стоит делать таких таблиц слишком много.
А для чего так много СУБД сейчас создается?
Они ведь все востребованы я так полагаю, в той или иной степени.
Нельзя обойтись старым, добрым MySQL или PostgreSQL?
Как только вам надо будет сделать GROUP BY по триллиону записей за пару секунд, вы поймете, почему Яндекс написал свою бд.
Можно почитать предыдущую статью Алексея: там написано про причины создания кликхауса
Странно что CLI не поддерживает автоматическое управление локальными таблицами (создание, удаление и тп) на всех серверах кластера при работе с Distributed таблицами? или все же можно?
Сейчас нельзя.

Например, DROP TABLE удаляет только локальную таблицу. Если написал DROP TABLE для Distributed-таблицы — удалится только сама Distributed-таблица («вид» на данные), а все данные останутся на месте.

Аналогично для Replicated-таблиц. Если сделал DROP TABLE — удалится одна реплика, и у таблицы станет на одну реплику меньше.

У нас есть задача «распределённые DDL», чтобы можно было одной командой манипулировать со всеми составляющими Distributed-таблиц. Но пока не очень спешим делать. К тому же, она, на всякий случай, будет работать только при каком-либо «снятом предохранителе».
Сколько места для сборки release нужно?) Случайно забил все 10G в /home совмещенном с / :-).

Будут ли пакеты для xenial?
Пакеты для Xenial, наверное, будут.
По крайней мере, поставлена задача.

Для запуска из корня ./release --standalone, вроде бы, 10 GB должно впритык хватить.
А если собираются все таргеты, которые есть в репозитории, то около 30 GB.
Какой формат данных будет самым эффективным для загрузки данных в ClickHouse, кроме Native разумеется? Какой формат выбрать чтобы можно было самостоятельно подготавливать данные для загрузки?
TabSeparated формат как правило является приемлимым по эффективности, если только вы умеете эффективно эскейпить значения типа String. Иногда с этим бывают проблемы. CSV будет тоже нормальным или чуть хуже.

Форматы Native и RowBinary эффективнее, но они не описаны подробно в документации.

При записи в таблицу семейства MergeTree, узким местом является скорее не парсинг формата, а сортировка данных, которую сервер производит при записи. Если отправлять уже отсортированные по первичному ключу данные, то сервер это поймёт, и загрузка будет идти быстрее. (Но если данные изначально не отсортированы, то вряд ли их удастся отсортировать эффективнее, чем это делает сервер).

При записи в простые таблицы Log/TinyLog, узким местом по CPU будет именно формат данных.

Лучше сначала попробовать загружать, как удобно. Например, формат JSONEachRow, конечно, менее эффективен, но если он оказался удобен для вас, то лучше начать с него.

Ещё замечу, что если данные постоянно загружаются на кластер (в реальном времени) и никогда не удаляются, то постоянный throughput по записи в расчёте на один сервер будет совсем небольшим (так как иначе вы просто за несколько дней заполнили бы все серверы). И при этом, запись не будет упираться в CPU и диски.
Меня интересует именно эффективность, «удобность» на втором плане. Таблицы имеют большое количество столбцов > 30 почти все данные hex(varbinary) или bigint или int, нужна именно производительность в скорости вставки данных, есть ли какие то показатели количества строк в секунду я конечно понимаю что все зависит от типа данных и количества столбцов но всеже я уверен что вы делали какие то бенчмарки)
Да. Это описано здесь.

Вставлять varbinary через TabSeparated формат довольно неудобно — надо будет эскейпить \t, \n, \\, что весьма неестественно для бинарных данных.

Можно рассмотреть формат RowBinary. Вкратце, он такой:
— числа пишутся в бинарном виде в little endian;
— String пишется в виде: длина в формате varint, затем байты строки;
— FixedString пишется просто как байты;
— Date пишется как UInt16 — число дней с unix эпохи, а DateTime как UInt32 — unix timestamp.
— все данные пишутся подряд, в порядке строк.
вай-вай. По сети передавать в little endian =(
Типы данных String, FixedString позволяют хранить произвольный набор байт, включая нулевые байты.
То есть, они заменяют CHAR, BINARY, VARCHAR, VARBINARY, TEXT, BLOB.
Если говорить про удобные и эффективные форматы, то у Druid'а есть WOW-фича — указываешь ему класс со структурой Protobuf, и он читает данные через неё. Сложно ли будет вкрутить подобную функциональность в clickhouse-client?
Эта задача имеет среднюю сложность, если рассматривать только один из сценариев работы.

Можно сделать поддержку protobuf-формата так, что можно будет читать данные из таблицы в некотором protobuf-е, который однозначно ей соответствует, и записывать данные в таблицу, но только в этой, конкретной структуре protobuf-а.

Но здесь не рассматривается другой сценарий работы — сгенерировать структуру таблицы по уже существующему protobuf-у. Будет сложность с protobuf-ами, имеющими более один уровень вложенности.
У нас есть в продакшене программа, которая перекладывает данные из сложного protobuf-а в ClickHouse, но она ещё при этом делает денормализацию: исходный protobuf содержит сессию, которая состоит из множества событий; и на один такой protobuf, в таблицу вставляется много строчек-событий.
В связи с этим, этот, более сложный сценарий, лучше вообще не рассматривать.
Да, с такими сценариями проще отдельную программу написать, которая с вложенными данными будет разбираться. Но ведь это не специфично для Protobuf, как в случае того же JSON'а поступать?..

В документации описан тип данных Nested, будет ли работать вставка данных, если структура таблицы с Nested-полями и во входящем JSON совпадает? Или на вход поддерживается только JSON с плоской структурой?
будет ли работать вставка данных, если структура таблицы с Nested-полями и во входящем JSON совпадает? Или на вход поддерживается только JSON с плоской структурой?

Nested будет представлен в виде отдельных массивов (одинаковых длин) для каждого элемента вложенной структуры.
Таким образом, прямое соответствие между иерархией в JSON и Nested типами не поддерживается.
Можно завести (по факту, запускали даже на AArch64 серверах). Для этого нужно найти все места в коде, где оно используется.
Найти их можно поиском по коду фрагмента _mm_ или __x86_64__.
Из SSE 4.2 используется совсем немного: crc32, строковые функции (в паре мест).
Это можно легко закрыть ifdef-ами.
И ещё: мы наблюдали, что на некоторых Openstack машинах, /proc/cpuinfo выдаёт неправильную информацию, хотя по факту, процессор выполняет нужные инструкции.
Огромная вам просьба: соберите, пожалуйста, кег под homebrew.

30 гигов компилять — это отпаяет макбук от монитора =(
Сервер без изменений работать не будет — есть Linux-специфичная функциональность. Но немного, и её можно сделать отключаемой.
Я сам не смогу это сделать, так как у меня нет Mac.
У вас в документации есть кусок про YT, может лучше убрать, чтоб не смущать общественность? https://clickhouse.yandex/reference_ru.html#Возможные глупые вопросы
По результатам внутреннего обсуждения, решили не убирать.
Почему-то не запускается сервер:

2016.06.17 21:47:32.477 [ 1 ] Application: DNS error: EAI: -9
2016.06.17 21:47:32.477 [ 1 ] Application: shutting down

В чем может быть причина?
Сделал, чтобы было более удобное сообщение об ошибке:

Cannot resolve listen_host (::), error: Address family for hostname not supported: -9. If it is an IPv6 address and your host has disabled IPv6, then consider to specify IPv4 address to listen in <listen_host> element of configuration file. Example: <listen_host>0.0.0.0</listen_host>
EAI_ADDRFAMILY  -9    /* Address family for NAME not supported.  */


Посмотрите вывод ifconfig.
Возможно, на сервере нет поддержки IPv6 (в принципе, даже link-local адреса), а для чего-то IPv6 нужен (в конфиге используется IPv6).
Может быть, стоит разобраться подробнее.
Да, IPv6 нет. Без него вообще никак?
UFO just landed and posted this here
Да, помогло, спасибо! Два часа бился!
Пока не знаю. Само наличие IPv6 связности не требуется, система нормально работает по IPv4.
У вас IPv6 где-то явно выключен? (ядро собрано без IPv6, или какие-то настройки) Если да, то где?
Непонятно, зачем отключать IPv6.

Может быть, поможет убрать все адреса вида :: из config.xml, users.xml, но скорее всего, не поможет.
И тогда помогла бы перекомпиляция, чтобы явно убрать IPv6 из DNS-запросов.
Помог совет выше, но все-равно спасибо.
А IPv6 не отключал — просто такой вот сервер.
Спасибо за труд, ребята! Вопрос, почему же в benchmark нет join, ведь по отношению к остальным участникам, например Vertica, это нечестно?
Запросы для бенчмарка были выбраны осенью 2013, и тогда ClickHouse не поддерживал JOIN.

Нам надо бы серьёзно обновить бенчмарк.
— сделать его на основе открытых данных;
— сделать запросы более разнообразными.

В этой директории есть заготовки: инструкции, как загрузить некоторые открытые данные и выполнить некоторые запросы.

В частности, есть заготовка для AMPLab Big Data Benchmark. Правда там всего три запроса, так что он тоже не особо интересен.
Понял, спасибо! В показательных целях очень стоит его добавить. Понятно что сканы сами по себе у вас быстрые, но вся мякотка аналитических (OLAP) движков именно вот в этих вот развесистых запросах. TPC-H load, условно говоря. Ну или взять ту же SAP HANA, которая (по крайней мере) утверждает, что никаких больше кубов и преагрегаций, все запросы прямо на колоночном движке с очень высокой скоростью.
o6CuFl2Q Если не сложно расскажите пожалуйста в чем преимущества и недостатки ClickHouse vs Tarantool? Какую СУБД лучше использовать для хранения показаний датчиков и построения графиков по этим данным?
Это принципиально разные системы.
Используйте ClickHouse для аналитики, а Tarantool как Key-Value базу.

В том числе, можно использовать и то, и другое.
На примере рекламной сети:

В Tarantool кладёте:
— данные для короткой персонализации;
— данные для таргетинга;
— счётчики для антифрода.

И используете его для запросов непосредственно из крутилки.

В ClickHouse кладёте:
— логи показов рекламы, вместе со всеми данными, свойствами посетителя, факторами;
— логи торгов, аукциона;
— логи кликов;
— постклик данные.

И используете его для построения отчётов:
— для внутреннего использования, для исследований, для оптимизации;
— в сервисе отчётов для клиентов.

Какую СУБД лучше использовать для хранения показаний датчиков и построения графиков по этим данным?

Это зависит от того, что нужно делать с этими датчиками.
Два варианта:
— по определённой логике принимать решение на каждый сигнал или на основе данных за короткое окно времени;
— эффективно хранить все данные и строить графики за любое время.
Спасибо, очень интересно!
Одно замечание — что в этой статье, что в документации очень хромает грамматика, глаз спотыкается постоянно.
Пишите, какие места следует исправить, и я постараюсь запомнить эти случаи.
Напимер:
Для решения этой задачи, открытых

уже в начале использования в 2012 году, была написана
.
И в документации много, например:
при чтении, вынимается достаточно большое
.

С запятыми беда, в общем. Перебор )
Спасибо. Действительно, у меня с ними проблемы. Постараюсь это проработать.
Не за что! Вам спасибо, Алексей!
Правильно ли я понимаю, что можно использовать вместо InfluxDB? Или лучше не стоит по каким-то причинам (требует сильно больше места, сложнее поддерживать и так далее)? Понятно, что для InfluxDB уже и Grafana есть, и поддержка 100500 пушеров, но это всё дело наживное.
Вот тут коротко отвечено.

ClickHouse подходит для хранения временных рядов.
Но нужно учесть несколько деталей.

ClickHouse не является готовой системой для работы с временными рядами и не является готовой системой мониторинга. ClickHouse — это СУБД. Вы можете хранить временные ряды в ней, но всю остальную обвязку, которая вам понадобится, придётся сделать самому или где-то взять.

Возможно, нам удастся через некоторое время открыть код интеграции ClickHouse и Graphite. Grafana с ним тоже работает.
А есть какой-то road map проекта (желательно публичный)? Просто одно дело, если вы один горите этим проектом, и другое дело, если в Яндексе есть амбиции достичь популярности хотя бы Tarantool (да, я знаю, что это разные продукты).

Еще интересно прочитать, как Танки работают с ClickHouse. Чем пушат, чем читают.
Публичного roadmap-а нет.
Основным «драйвером» развития проекта являются потребности Яндекс.Метрики, ещё часть — остальных сервисов внутри Яндекса.
Не стоит недооценивать эти потребности :)
Про амбиции ничего сказать не могу.

Еще интересно прочитать, как Танки работают с ClickHouse. Чем пушат, чем читают.

Это может рассказать doctornkz.
Привет! Спасибо за интерес к связке Танка и ClickHouse. Сейчас это часть закрытого плагина для Танка, но в скором времени мы выложим специальный writer для подключения Танка к CH. Следите за новостями и приходите обязательно к нам в чатик на gitter, так как чем выше интерес к этой связке, тем быстрее мы выложим writer в opensource. От себя добавлю, что CH решил много наших проблем с хранением, скоростью и масштабируемостью, он крутой.
а инфлюксдб уже работает хотя бы на 100 записей в секунду?
Я не пробовал еще последнюю версию (1.0b которая), но предыдущие испытывают проблемы и на меньшем масштабе. В принципе, если это что-то не сверх критичное (типа данных нагрузочных тестов), то можно и рестартить время от времени, чтобы дать «продышаться», но, в целом, удовлетворения нет — поэтому я и задумываюсь о замене.
мы начали переделывать хранение в одном нашем сервисе на него, выглядит впечатляюще.
было бы прикольно, если бы вы побольше инфы писали в хттп-хедеры ответа: время запроса, время работы с диском. Мы так делаем в нашем флюссонике.

Если получится, то может мы попробуем сделать пулл-реквест.
Не получается, если запрос потоковый (начинает отдавать данные до окончания выполнения).
Так мы даже не можем поменять код ответа с 200 на 500, если после начала отдачи части данных произошёл эксепшен.
Разве что использовать HTTP Trailers, которые почти никто не поддерживает.

Время выполнения запроса пишется, например, при использовании форматов JSON, JSONCompact — внутри JSON-а.

Для собственных нужд нашей компании, начали разработку PHP клиента ClickHouse.
На данный момент, клиент в процессе разработки, но уже кое-что умеет.
В планах сделать мощный клиент, покрывающий максимальное кол-во потребностей.


Естественно Open-source, лицензия MIT.


Будем рады, любому участию в проекте.
Присылайте Pull requests, задавайте вопросы, пожелания, ну или просто используйте для собственных нужд.


Packagist: https://packagist.org/packages/8bitov/clickhouse-php-client
GitHub: https://github.com/8bitov/clickhouse-php-client
Документация(пока пустая): https://clickhouse.readme.io/

И конечно, большая благодарность за прекрасный продукт, компании Yandex, Алексею и всем, кто принимал участие в проекте.
Спасибо!

По аналогии с вами мы работаем над клиентом для Go.
Из интересного: поддерживается health check. То есть если какой-то из мастеров MergeTree падает, то к нему не будут идти запросы.
Контрибьюторы приветствуются. :)

https://github.com/roistat/go-clickhouse
Спасибо, я думаю, будет полезно!
Ещё хорошо бы написать сюда.
Выглядит потрясающе. Всё присматриваюсь попробовать. В любом случае спасибо большое за открытие, да ещё под такой разрешительной лицензией.

Скажите пожалуйста, в тестах вы в основном называете Vertica. А что с cassandra? И даже пожалуй куда более интересно с scylladb? По их маркетинговым заверениям на сайте «A Cassandra compatible NoSQL column store, at 1MM transactions/sec per server.». Маркетинг оно понятно, всегда впереди, но что-то же должно быть под их обещаниями… Вы не пробовали или не планируете провести сравнение с ними на каких-то открытых данных?
Надо бы провести.

Но я бы не ожидал высоких результатов Cassandra (и ScyllaDB) на тех же запросах по следующим причинам:
(сразу скажу, что у меня нет глубоких представлений о том, как работает Cassandra, я исхожу из поверхностных сведений)

1. В Cassandra больше упор на полуструктурированные данные, по аналогии с BigTable. Можно иметь совершенно разный набор столбцов для разных ключей; количество столбцов может быть неограниченным. Но такой способ хранения данных менее оптимальный для их сканирования. Грубо говоря, на каждый ключ, во время чтения, приходится разбираться с тем, какие столбцы для него есть. Для сравнения, в ClickHouse структура таблицы жёсткая, хотя столбцов может быть достаточно много, и значения в них могут быть сильно разреженными.

2. Cassandra больше ориентирована на key-value сценарий работы: чтение и обновление данных по ключу.
Но в аналитических базах данных, чтение по ключу с низкой latency не требуется, и за счёт этого становятся допустимы такие оптимизации, как блочное сжатие данных более крупными блоками и разреженный индекс. В аналитических базах данных, одной строчке уделяется мало внимания, вся обработка данных рассчитана на обработку целыми пачками.
Чтобы уметь обновлять данные по ключу, требуется на каждую строчку иметь некоторые дополнительные данные — например, номер версии и timestamp. В Cassandra используется LSM-Tree, значит при обновлении, в базу пишутся записи вида «что и как обновить». Эти записи надо мерджить при чтении и это довольно дорого, если требуется выполнять не точечные чтения, а обработку пачек данных. В аналитических базах данных, для эффективного обновления данных, требуются сложные оптимизации.

Теперь рассмотрим, что такое «1MM transactions/sec per server». (1MM в переводе на русский — это один миллион.)
В контексте сравнения с аналитической СУБД это говорит только о том, что ScyllaDB — не аналитическая СУБД.
Для аналитических СУБД производительность измеряется в других величинах: пропускная способность при обработке одного или небольшого количества одновременных сложных запросов.

Не стоит думать, что я принижаю ScyllaDB. Давно хотел изучить для применения как key-value базу.
В этом смысле 1 млн. операций в секунду — очень хороший результат.
(Но стоит иметь ввиду, что, исходя из возможностей железа, специализированное решение могло бы работать намного быстрее.)
Добавлю к словам, сказанным o6CuFl2Q.

Cassandra — это не колоночная СУБД. Сравнивать ее с ClickHouse нельзя.

Cassandra — key-value хранилище «на стероидах». Она конкурирует с HBase, Aerospike и подобными. Вы можете очень быстро записывать туда данные. Можете очень быстро получить любую запись по ключу. Но вы не можете сделать count(id) на петабайтовом кластере за секунду.
Разумеется и у Cassandra, и у остальных конкурентов есть возможности делать аналитические запросы через MapReduce, однако из-за неколоночной структуры хранения данных такие запросы отнимают все равно слишком много времени и ресурсов.

Сравнивать ClickHouse надо с Kudu и EventQL.
Было бы круто парни, еслиб вы завели канал на gitter, community все таки еще не большое а вопросы возникают часто!
Боюсь, что нам довольно непривычно будет отвечать на вопросы в режиме чата. Поэтому gitter не делаем.
У нас скоро состоится встреча:
Яндекс изнутри: инфраструктура хранения и обработки данных.

Встреча пройдёт в Москве. Участие бесплатное.
В рамках встречи будет, в том числе, небольшой доклад про ClickHouse, а также неограниченное время для вопросов и ответов.
Начну с того, что продукт хороший — наконец-то, на Российском рынке начали производить что-то подобное.
Так же замечу правильный выбор SQL-синтаксиса подобного MySQL — многие знают и долгое время использовали, что безусловно поможет в применении на практике разработчиками любого уровня.

Вопрос — выполнил запрос с загруженными данными в таблице ontime:

SELECT 
    OriginCityName, 
    count() AS c, 
    avg(DepDelay > 60) AS delays
FROM ontime 
GROUP BY OriginCityName
HAVING c > 100000
ORDER BY delays DESC
LIMIT 20 


У вас этот запрос выполнился с результатом:
20 rows in set. Elapsed: 0.546 sec. Processed 166.63 million rows, 4.36 GB (82.72 million rows/s., 2.17 GB/s.)

На моей машине — Intel® Core(TM) i7-3630QM CPU @ 2.40GHz, 4x2=8 logical cores RAM 16Gb/DDR3/1600, SSD KINGSTON SVP200S:
20 rows in set. Elapsed: 2.014 sec. Processed 166.63 million rows, 4.36 GB (82.72 million rows/s., 2.17 GB/s.)

Первое, что подумалось — может у них запрос был уже в кэше, выполнил повторно — результат такой же, в кэш (память heap/pile) не лезет. Соответственно, можно ли добавить запрос в кэш для достижения такого же результата, как в вашем примере или может конфиг подтьюнить как-нибудь? Все-таки разница ~ х4.
Спасибо за добрые слова!

Разница в скорости выполнения объясняется количеством ядер.
Мы выполняли запросы на сервере с 16x2 ядер. Если точнее, на таком.

У вас 4x2 ядер. Как раз разница в 4 раза.
Это показывает, что выполнение запросов масштабируется по ядрам CPU.
28 февраля состоится митап в Санкт-Петербурге.

В программе рассказ про последние разработки в ClickHouse, про использование ClickHouse в аналитике Яндекса и, конечно, будет выделено почти неограниченное время для ответов на вопросы.
3 апреля мы организуем ClickHouse митап в Новосибирске.

В программе пара докладов и неограниченное время для ответов на вопросы.
Если вы в Новосибирске — приходите на встречу, и мы расскажем вам про ClickHouse всё, что вы захотите узнать.

(Я не археолог)


Cпасибо вам большое за ClickHouse.

Sign up to leave a comment.