ClickHouse

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 16:02, 19 мая 2020.
ClickHouse
Clickhouse.png
Разработчики: Яндекс
Выпущена: 23 сентября 1997
Операционная система: Linux
Локализация: English
Тип ПО: СУБД
Лицензия: Open-source
Веб-сайт clickhouse.yandex

ClickHouse — это столбцовая СУБД для OLAP (online обработки аналитических запросов). [Источник 1]

Содержание

История создания

Изначально ClickHouse разрабатывалась исключительно для задач Яндекс.Метрики — чтобы строить отчёты в интерактивном режиме по неагрегированным логам пользовательских действий. В связи с тем, что система является полноценной СУБД и обладает весьма широкой функциональностью, уже в начале использования в 2012 году, была написана подробная документация. Это отличает ClickHouse от многих типичных внутренних разработок — специализированных и встраиваемых структур данных для решения конкретных задач, таких как, например, Metrage и OLAPServer. [Источник 2]

Развитая функциональность и наличие детальной документации привели к тому, что ClickHouse постепенно распространился по многим отделам Яндекса. Неожиданно оказалось, что система может быть установлена по инструкции и работает «из коробки», то есть не требует привлечения разработчиков. ClickHouse стал использоваться в Директе, Маркете, Почте, AdFox, Вебмастере, в мониторингах и в бизнес-аналитике. ClickHouse позволял либо решать задачи, для которых раньше не было подходящих инструментов, либо решать задачи на порядки эффективнее, чем другие системы.

Постепенно возник спрос на использование ClickHouse не только во внутренних продуктах Яндекса. Например, в 2013 году, ClickHouse применялся для анализа метаданных о событиях эксперимента LHCb в CERN. Система могла бы использоваться более широко, но в то время этому мешал закрытый статус. Другой пример: open-source технология Яндекс.Танк внутри Яндекса использует ClickHouse для хранения данных телеметрии, тогда как для внешних пользователей в качестве базы данных был доступен только MySQL, который плохо подходит для данной задачи.

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

Расширение пользовательской базы позволяет рассматривать примеры использования, которые без этого едва ли пришли бы в голову. Также это позволяет быстрее находить ошибки и неудобства, которые имеют значение в том числе и для основного применения ClickHouse — в Метрике. Без сомнения, всё это повышает качество продукта. Поэтому было принято решение сделать ClickHouse открытым сегодня.

Характеристики

Основные характеристики базы данных ClickHouse:

  1. Действительно столбцовая СУБД. Рядом с данными не хранятся другие величины, например, в ClickHouse поддерживаются значения постоянной длины, чтобы не хранить рядом размер типа.
  2. Линейная масштабируемость. Система позволяет увеличивать кластер добавлением серверов.
  3. Отказоустойчивость. Система представляет собой кластер шардов, где каждый шард — это группа реплик. Используется асинхронная multimaster репликация: после записи на любую доступную реплику, данные распространяются на все остальные реплики. Для координации работы реплик используется ZooKeeper (ZooKeeper не участвует в процессе обработки и выполнения запроса).
  4. Способность работать с большими данными (триллионы записей и петабайты данных).
  5. Поддержка SQL. ClickHouse поддерживает диалект SQL c расширениями: массивы и вложенные структуры данных, вероятностные структуры, функция по работе с URI, возможность подключить внешнее key-value хранилище и т. д.
  6. Высокая эффективность работы. Векторные вычисления; данные не только хранятся по столбцам, но и обрабатываются по векторам (кусочкам столбцов), за счёт чего достигается высокая эффективность по CPU; наличие функциональности для семплирования и приблизительных вычислений; параллельная и распределенная обработка запросов (в том числе JOIN'ов).
  7. Сжатие данных.
  8. СУБД оптимизирована для работы на HDD-дисках. Можно обрабатывать данные, которые не помещаются в оперативную память.
  9. Разнообразные клиенты для подключения к БД. Для работы с базой данных можно использовать консольный клиент, HTTP API и ряд wrapper’ов на Python, PHP, NodeJS, Perl, Ruby и R. Также для ClickHouse есть JDBC и Golang драйверы.
  10. Подробная документация.

Применение

Разный порядок хранения данных лучше подходит для разных сценариев работы. Сценарий работы с данными - это то, какие производятся запросы, как часто и в каком соотношении; сколько читается данных на запросы каждого вида - строк, столбцов, байт; как соотносятся чтения и обновления данных; какой рабочий размер данных и насколько локально он используется; используются ли транзакции и с какой изолированностью; какие требования к дублированию данных и логической целостности; требования к задержкам на выполнение и пропускной способности запросов каждого вида и т.п.[Источник 3]

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

Ключевые особенности OLAP сценария работы

  • подавляющее большинство запросов - на чтение;
  • данные обновляются достаточно большими пачками (> 1000 строк), а не по одной строке, или не обновляются вообще;
  • данные добавляются в БД, но не изменяются;
  • при чтении, вынимается достаточно большое количество строк из БД, но только небольшое подмножество столбцов;
  • таблицы являются «широкими», то есть, содержат большое количество столбцов;
  • запросы идут сравнительно редко (обычно не более сотни в секунду на сервер);
  • при выполнении простых запросов, допустимы задержки в районе 50 мс;
  • значения в столбцах достаточно мелкие - числа и небольшие строки (пример - 60 байт на URL);
  • требуется высокая пропускная способность при обработке одного запроса (до миллиардов строк в секунду на один сервер);
  • транзакции отсутствуют;
  • низкие требования к консистентности данных;
  • в запросе одна большая таблица, все таблицы кроме одной маленькие;
  • результат выполнения запроса существенно меньше исходных данных - то есть, данные фильтруются или агрегируются; результат выполнения помещается в оперативку на одном сервере.

Легко видеть, что OLAP сценарий работы существенно отличается от других распространённых сценариев работы (например, OLTP или Key-Value сценариев работы). Таким образом, не имеет никакого смысла пытаться использовать OLTP или Key-Value БД для обработки аналитических запросов, если вы хотите получить приличную производительность («выше плинтуса»). Например, если вы попытаетесь использовать для аналитики MongoDB или Redis - вы получите анекдотически низкую производительность по сравнению с OLAP-СУБД.

Причины, по которым столбцовые СУБД лучше подходят для OLAP сценария

Столбцовые СУБД лучше (от 100 раз по скорости обработки большинства запросов) подходят для OLAP сценария работы. Причины в деталях будут разъяснены ниже, а сам факт проще продемонстрировать визуально(см. рисунок 1 и рисунок 2:

Рисунок 1 – Строковые СУБД
Рисунок 2– Столбцовые СУБД


По вводу-выводу

1. Для выполнения аналитического запроса, требуется прочитать небольшое количество столбцов таблицы. В столбцовой БД для этого можно читать только нужные данные. Например, если вам требуется только 5 столбцов из 100, то следует рассчитывать на 20-кратное уменьшение ввода-вывода. 2. Так как данные читаются пачками, то их проще сжимать. Данные, лежащие по столбцам также лучше сжимаются. За счёт этого, дополнительно уменьшается объём ввода-вывода. 3. За счёт уменьшения ввода-вывода, больше данных влезает в системный кэш.

Например, для запроса «посчитать количество записей для каждой рекламной системы», требуется прочитать один столбец «идентификатор рекламной системы», который занимает 1 байт в несжатом виде. Если большинство переходов было не с рекламных систем, то можно рассчитывать хотя бы на десятикратное сжатие этого столбца. При использовании быстрого алгоритма сжатия, возможно разжатие данных со скоростью более нескольких гигабайт несжатых данных в секунду. То есть, такой запрос может выполняться со скоростью около нескольких миллиардов строк в секунду на одном сервере. На практике, такая скорость действительно достигается.

По вычислениям

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

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

2. Кодогенерация. Для запроса генерируется код, в котором подставлены все косвенные вызовы.

В «обычных» БД этого не делается, так как не имеет смысла при выполнении простых запросов. Хотя есть исключения. Например, в MemSQL кодогенерация используется для уменьшения latency при выполнении SQL запросов. Для сравнения, в аналитических СУБД требуется оптимизация throughput, а не latency.

Стоит заметить, что для эффективности по CPU требуется, чтобы язык запросов был декларативным (SQL, MDX) или хотя бы векторным (J, K). То есть, чтобы запрос содержал циклы только в неявном виде, открывая возможности для оптимизации.


Отличительные возможности ClickHouse

По-настоящему столбцовая СУБД

В по-настоящему столбцовой СУБД рядом со значениями не хранится никаких лишних данных. Например, должны поддерживаться значения постоянной длины, чтобы не хранить рядом со значениями типа «число» их длины. Для примера, миллиард значений типа UInt8 должен действительно занимать в несжатом виде около 1GB, иначе это сильно ударит по эффективности использования CPU. Очень важно хранить данные компактно (без «мусора») в том числе в несжатом виде, так как скорость разжатия (использование CPU) зависит, в основном, от объёма несжатых данных.

Этот пункт пришлось выделить, так как существуют системы, которые могут хранить значения отдельных столбцов по отдельности, но не могут эффективно выполнять аналитические запросы в силу оптимизации под другой сценарий работы. Примеры: HBase, BigTable, Cassandra, HyperTable. В этих системах вы получите пропускную способность в районе сотен тысяч строк в секунду, но не сотен миллионов строк в секунду.

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

Сжатие данных

Некоторые столбцовые СУБД (InfiniDB CE, MonetDB) не используют сжатие данных. Однако сжатие данных действительно играет одну из ключевых ролей в демонстрации отличной производительности.

Хранение данных на диске

Многие столбцовые СУБД (SAP HANA, Google PowerDrill) могут работать только в оперативной памяти. Такой подход стимулирует выделять больший бюджет на оборудование, чем фактически требуется для анализа в реальном времени. ClickHouse спроектирован для работы на обычных жестких дисках, что обеспечивает низкую стоимость хранения на гигабайт данных, но SSD и дополнительная оперативная память тоже полноценно используются, если доступны.

Параллельная обработка запроса на многих процессорных ядрах

Большие запросы естественным образом распараллеливаются, используя все необходимые ресурсы из доступных на сервере.

Распределённая обработка запроса на многих серверах

Почти все перечисленные ранее столбцовые СУБД не поддерживают распределённую обработку запроса. В ClickHouse данные могут быть расположены на разных шардах. Каждый шард может представлять собой группу реплик, которые используются для отказоустойчивости. Запрос будет выполнен на всех шардах параллельно. Это делается прозрачно для пользователя.

Поддержка SQL

ClickHouse поддерживает декларативный язык запросов на основе SQL и во многих случаях совпадающий с SQL стандартом. Поддерживаются GROUP BY, ORDER BY, подзапросы в секциях FROM, IN, JOIN, а также скалярные подзапросы. Зависимые подзапросы и оконные функции не поддерживаются.

Векторный движок

Данные не только хранятся по столбцам, но и обрабатываются по векторам - кусочкам столбцов. За счёт этого достигается высокая эффективность по CPU.

Обновление данных в реальном времени

ClickHouse поддерживает таблицы с первичным ключом. Для того, чтобы можно было быстро выполнять запросы по диапазону первичного ключа, данные инкрементально сортируются с помощью merge дерева. За счёт этого, поддерживается постоянное добавление данных в таблицу. Блокировки при добавлении данных отсутствуют.

Наличие индекса

Физическая сортировка данных по первичному ключу позволяет получать данные для конкретных его значений или их диапазонов с низкими задержками - менее десятков миллисекунд.

Подходит для онлайн запросов

Низкие задержки позволяют не откладывать выполнение запроса и не подготавливать ответ заранее, а выполнять его именно в момент загрузки страницы пользовательского интерфейса. То есть, в режиме онлайн.

Поддержка приближённых вычислений

ClickHouse предоставляет различные способы разменять точность вычислений на производительность:

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

Репликация данных и поддержка целостности

Используется асинхронная multimaster репликация. После записи на любую доступную реплику, данные распространяются на все остальные реплики в фоне. Система поддерживает полную идентичность данных на разных репликах. Восстановление после большинства сбоев осуществляется автоматически, а в сложных случаях — полуавтоматически. При необходимости, можно включить кворумную запись данных.

Особенности, которые могут считаться недостатками

1. Отсутствие полноценных транзакций. 2. Возможность изменять или удалять ранее записанные данные с низкими задержками и высокой частотой запросов не предоставляется. Есть массовое удаление и изменение данных для очистки более не нужного или соответствия GDPR. 3. Разреженный индекс делает ClickHouse плохо пригодным для точечных чтений одиночных строк по своим ключам.

C++ клиентская библиотека

Поддерживаемые типы данных

  • Array(T)
  • Date
  • DateTime
  • Decimal32, Decimal64, Decimal128
  • Enum8, Enum16
  • FixedString(N)
  • Float32, Float64
  • IPv4, IPv6
  • Nullable(T)
  • String
  • Tuple
  • UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64

Сборка

$ mkdir build .
$ cd build
$ cmake .. [-DBUILD_TESTS=ON]
$ make

Пример использования

#include <clickhouse/client.h>

using namespace clickhouse;

/// Initialize client connection.
Client client(ClientOptions().SetHost("localhost"));

/// Create a table.
client.Execute("CREATE TABLE IF NOT EXISTS test.numbers (id UInt64, name String) ENGINE = Memory");

/// Insert some values.
{
    Block block;

    auto id = std::make_shared<ColumnUInt64>();
    id->Append(1);
    id->Append(7);

    auto name = std::make_shared<ColumnString>();
    name->Append("one");
    name->Append("seven");

    block.AppendColumn("id"  , id);
    block.AppendColumn("name", name);

    client.Insert("test.numbers", block);
}

/// Select values inserted in the previous step.
client.Select("SELECT id, name FROM test.numbers", [] (const Block& block)
    {
        for (size_t i = 0; i < block.GetRowCount(); ++i) {
            std::cout << block[0]->As<ColumnUInt64>()->At(i) << " "
                      << block[1]->As<ColumnString>()->At(i) << "\n";
        }
    }
);

/// Delete table.
client.Execute("DROP TABLE test.numbers");


HTTP-интерфейс

HTTP интерфейс позволяет использовать ClickHouse на любой платформе, из любого языка программирования HTTP интерфейс более ограничен по сравнению с родным интерфейсом, но является более совместимым.

По умолчанию, clickhouse-server слушает HTTP на порту 8123 (это можно изменить в конфиге). Если запросить GET / без параметров, то вернётся строка заданная с помощью настройки http_server_default_response. Значение по умолчанию «Ok.» (с переводом строки на конце).

$ curl 'http://localhost:8123/'
Ok.

В скриптах проверки доступности можно использовать GET /ping без параметров. Если сервер доступен всегда возвращается «Ok.» (с переводом строки на конце).

$ curl 'http://localhost:8123/ping'
Ok.

Запрос отправляется в виде URL параметра с именем query. Или как тело запроса при использовании метода POST. Или начало запроса в URL параметре query, а продолжение POST-ом (зачем это нужно, будет объяснено ниже). Размер URL ограничен 16KB, это следует учитывать при отправке больших запросов.

В случае успеха, вам вернётся код ответа 200 и результат обработки запроса в теле ответа. В случае ошибки, вам вернётся код ответа 500 и текст с описанием ошибки в теле ответа.

При использовании метода GET, выставляется настройка readonly. То есть, для запросов, модифицирующие данные, можно использовать только метод POST. Сам запрос при этом можно отправлять как в теле POST-а, так и в параметре URL.

Примеры:

$ curl 'http://localhost:8123/?query=SELECT%201'
1

$ wget -O- -q 'http://localhost:8123/?query=SELECT 1'
1

$ echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
HTTP/1.0 200 OK
Date: Wed, 27 Nov 2019 10:30:18 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
X-ClickHouse-Server-Display-Name: clickhouse.ru-central1.internal
X-ClickHouse-Query-Id: 5abe861c-239c-467f-b955-8a201abb8b7f
X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}

1

Как видно, curl немного неудобен тем, что надо URL-эскейпить пробелы. Хотя wget сам всё эскейпит, но его не рекомендуется использовать, так как он плохо работает по HTTP 1.1 при использовании keep-alive и Transfer-Encoding: chunked.

$ echo 'SELECT 1' | curl 'http://localhost:8123/' --data-binary @-
1

$ echo 'SELECT 1' | curl 'http://localhost:8123/?query=' --data-binary @-
1

$ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
1

Если часть запроса отправляется в параметре, а часть POST-ом, то между этими двумя кусками данных ставится перевод строки. Пример (так работать не будет):

$ echo 'ECT 1' | curl 'http://localhost:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception

По умолчанию, данные возвращаются в формате TabSeparated. Можно попросить любой другой формат - с помощью секции FORMAT запроса. Возможность передавать данные POST-ом нужна для INSERT-запросов. В этом случае можно написать начало запроса в параметре URL, а вставляемые данные передать POST-ом. Вставляемыми данными может быть, например, tab-separated дамп, полученный из MySQL. Таким образом, запрос INSERT заменяет LOAD DATA LOCAL INFILE из MySQL.

Примеры: Создаём таблицу:

$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-

Используем привычный запрос INSERT для вставки данных:

$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-

Данные можно отправить отдельно от запроса:

$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-

Можно указать любой формат для данных. Формат Values - то же, что используется при записи INSERT INTO t VALUES:

$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-

Можно вставить данные из tab-separated дампа, указав соответствующий формат:

$ echo -ne '10\n11\n12\n' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-

Прочитаем содержимое таблицы. Данные выводятся в произвольном порядке из-за параллельной обработки запроса:

$ curl 'http://localhost:8123/?query=SELECT%20a%20FROM%20t'
7
8
9
10
11
12
1
2
3
4
5
6

Удаляем таблицу.

$ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @-

Для запросов, которые не возвращают таблицу с данными, в случае успеха, выдаётся пустое тело ответа.

Можно использовать внутренний формат сжатия Clickhouse при передаче данных. Формат сжатых данных нестандартный, и вам придётся использовать для работы с ним специальную программу clickhouse-compressor (устанавливается вместе с пакетом clickhouse-client). Для повышения эффективности вставки данных можно отключить проверку контрольной суммы на стороне сервера с помощью настройки http\_native\_compression\_disable\_checksumming\_on\_decompress.

Если указан compress = 1 в URL, то сервер сжимает данные, которые он отправляет. Если указан decompress = 1 в URL, сервер распаковывает те данные, которые вы передаёте методом POST.

Также, можно использовать HTTP compression. Для отправки сжатого запроса POST, добавьте заголовок Content-Encoding: compression_method\. Чтобы ClickHouse сжимал ответ, добавьте заголовок Accept-Encoding: compression_method. ClickHouse поддерживает следующие методы сжатия: gzip, br, and deflate . Чтобы включить HTTP compression, используйте настройку ClickHouse enable\_http\_compression. Уровень сжатия данных для всех методов сжатия можно настроить с помощью настройки http\_zlib\_compression\_level.

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

Примеры отправки данных со сжатием:

$ #Отправка данных на сервер:
$ curl -vsS "http://localhost:8123/?enable_http_compression=1" -d 'SELECT number FROM system.numbers LIMIT 10' -H 'Accept-Encoding: gzip'

$ #Отправка данных клиенту:
$ echo "SELECT 1" | gzip -c | curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/'

Важно:

 Некоторые HTTP-клиенты могут по умолчанию распаковывать данные (gzip и deflate) с сервера в фоновом режиме и вы можете получить распакованные данные, даже если правильно используете настройки сжатия.

В параметре URL database может быть указана БД по умолчанию.

$ echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
0
1
2
3
4
5
6
7
8
9

По умолчанию используется БД, которая прописана в настройках сервера, как БД по умолчанию. По умолчанию, это - БД default. Также вы всегда можете указать БД через точку перед именем таблицы.

Имя пользователя и пароль могут быть указаны в одном из трёх вариантов:

  • С использованием HTTP Basic Authentication. Пример:
$ echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
  • В параметрах URL user и password. Пример:
$ echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-
  • С использованием заголовков ‘X-ClickHouse-User’ и ‘X-ClickHouse-Key’. Пример:
$ echo 'SELECT 1' | curl -H 'X-ClickHouse-User: user' -H 'X-ClickHouse-Key: password' 'http://localhost:8123/' -d @-

Если пользователь не задан,то используется default. Если пароль не задан, то используется пустой пароль. Также в параметрах URL вы можете указать любые настройки, которые будут использованы для обработки одного запроса, или целые профили настроек.

Пример:

http://localhost:8123/?profile=web&max\_rows\_to\_read=1000000000&query=SELECT+1
$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
0
1
2
3
4
5
6
7
8
9

Аналогично можно использовать ClickHouse-сессии в HTTP-протоколе. Для этого необходимо добавить к запросу GET параметр session_id. В качестве идентификатора сессии можно использовать произвольную строку. По умолчанию через 60 секунд бездействия сессия будет прервана. Можно изменить этот таймаут, изменяя настройку default_session_timeout в конфигурации сервера, или добавив к запросу GET параметр session_timeout. Статус сессии можно проверить с помощью параметра session_check=1. В рамках одной сессии одновременно может исполняться только один запрос.

Прогресс выполнения запроса можно отслеживать с помощью заголовков ответа X-ClickHouse-Progress. Для этого включите send\_progress\_in\_http\_headers. Пример последовательности заголовков:

 
X-ClickHouse-Progress: {"read_rows":"2752512","read_bytes":"240570816","total_rows_to_read":"8880128"}
X-ClickHouse-Progress: {"read_rows":"5439488","read_bytes":"482285394","total_rows_to_read":"8880128"}
X-ClickHouse-Progress: {"read_rows":"8783786","read_bytes":"819092887","total_rows_to_read":"8880128"}

Возможные поля заголовка:

  • read_rows — количество прочитанных строк.
  • read_bytes — объём прочитанных данных в байтах.
  • total_rows_to_read — общее количество строк для чтения.
  • written_rows — количество записанных строк.
  • written_bytes — объём прочитанных данных в байтах.

Запущенные запросы не останавливаются автоматически при разрыве HTTP соединения. Парсинг и форматирование данных производится на стороне сервера и использование сети может быть неэффективным. Может быть передан необязательный параметр query\_id - идентификатор запроса, произвольная строка.

Может быть передан необязательный параметр quota\_key - ключ квоты, произвольная строка. HTTP интерфейс позволяет передать внешние данные (внешние временные таблицы) для использования запроса.

Буферизация ответа

Существует возможность включить буферизацию ответа на стороне сервера. Для этого предусмотрены параметры URL buffer_size и wait_end_of_query.

buffer_size определяет количество байт результата которые будут буферизованы в памяти сервера. Если тело результата больше этого порога, то буфер будет переписан в HTTP канал, а оставшиеся данные будут отправляться в HTTP-канал напрямую.

Чтобы гарантировать буферизацию всего ответа необходимо выставить wait_end_of_query=1. В этом случае данные, не поместившиеся в памяти, будут буферизованы во временном файле сервера.

Пример:

$ curl -sS 'http://localhost:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d 'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'

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

Запросы с параметрами

Можно создать запрос с параметрами и передать для них значения из соответствующих параметров HTTP-запроса. Отформатируйте запрос обычным способом. Представьте значения, которые вы хотите передать из параметров приложения в запрос в следующем формате:

{<name>:<data type>}
  • name — идентификатор подстановки. В консольном клиенте его следует использовать как часть имени параметра --param_<name> = value.
  • data type — тип данных значения. Например, структура данных (integer, ('string', integer)) может иметь тип данных Tuple(UInt8, Tuple(String, UInt8)) (целочисленный тип может быть и другим).

Пример

$ curl -sS "<address>?param_id=2¶m_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"

MySQL-интерфейс

ClickHouse поддерживает взаимодействие по протоколу MySQL. Данная функция включается настройкой mysql\_port в конфигурационном файле:

<mysql_port>9004</mysql_port>

Пример подключения с помощью стандартного клиента mysql:

$ mysql --protocol tcp -u default -P 9004

Вывод в случае успешного подключения:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 20.2.1.1-ClickHouse

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Для совместимости со всеми клиентами рекомендуется задавать пароль пользователя в конфигурационном файле с помощью двойного хэша SHA1. В случае указания пароля с помощью SHA256 некоторые клиенты не смогут пройти аутентификацию (mysqljs и старые версии стандартного клиента mysql).

Ограничения:

  • не поддерживаются подготовленные запросы
  • некоторые типы данных отправляются как строки

Установка ClickHouse

Установка ClickHouse будет производиться на операционной системе Ubuntu 16.04 Xenial. На Ubuntu и Debian Linux вы можете установить ClickHouse из готовых пакетов. На других Linux-системах, можно собрать ClickHouse из исходников и установить его самостоятельно.

Пакет clickhouse-client содержит программу clickhouse-client — клиент ClickHouse для работы в интерактивном режиме. Пакет clickhouse-server-base содержит бинарный файл clickhouse-server, а clickhouse-server-common — конфигурационные файлы к серверу. Выполняем следующие команды:[Источник 4]

sudo apt-add-repository "deb http://repo.yandex.ru/clickhouse/trusty stable main"
sudo apt-get update
sudo apt-get install clickhouse-server-common clickhouse-client -y

Сервер не запускается самостоятельно при установке пакета и не перезапускается сам при обновлении. Для запуска сервера, необходимо выполнить:

sudo service clickhouse-server start

Для работы в интерактивном режиме:

clickhouse-client

После выполненных команд окно имеет следующий вид (рисунок 3):

Рисунок 3 – Вид окна

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

Для создания таблицы t с двумя столбцами b и a типа String и Int соответственно необходимо выполнить следующее (см. рисунок 4):

CREATE TABLE t (b String, a UInt8) ENGINE = Memory
Рисунок 4 – Создание таблицы

Для того чтобы создать в новой таблице записи необходимо воспользоваться командой INSERT. Проверим, что записи появились с помощью команды SELECT:

INSERT INTO t VALUES ('first', 2), ('second', 15), ('third', 8)
SELECT * FROM t

Результат на экране представлен на рисунке 5:

Рисунок 5 – Добавление записей

Выведем на экран все b, значения а для которых больше 7 (см. рисунок 6):

SELECT b FROM t WHERE a>7
Рисунок 6 – Работа с командой SELECT

Для удаления таблицы нужно воспользоваться командой DROP TABLE. Убедимся, что таблица отсутствует с помощью команды SELECT. (см. рисунок 7)

DROP TABLE t
SELECT * FROM t
Рисунок 7 – Удаление таблицы

Источники

  1. ClickHouse [Электронный ресурс] — Дата обращения: 19.11.2017. Режим доступа: https://ru.wikipedia.org/wiki/ClickHouse
  2. Яндекс открывает ClickHouse [Электронный ресурс] — Дата обращения: 19.11.2017. Режим доступа: https://habrahabr.ru/company/yandex/blog/303282/
  3. ClickHouse. Руководство [Электронный ресурс] — Дата обращения: 06.05.2020. Режим доступа
    https://clickhouse.tech/docs/ru/
  4. ClickHouse [Электронный ресурс] — Дата обращения: 19.11.2017. Режим доступа: https://clickhouse.yandex