Перейти к основному содержимому
Перейти к основному содержимому

Могу ли я использовать ClickHouse в качестве хранилища ключ-значение?

Краткий ответ — "нет". Нагрузки типа ключ-значение занимают одни из первых позиций в списке случаев, когда НЕ следует использовать ClickHouse. В конце концов, это система OLAP, в то время как существует множество отличных систем хранения ключ-значение.

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

Если вы решили пойти против рекомендаций и выполнять некоторые запросы, похожие на ключ-значение, к ClickHouse, вот несколько советов:

  • Основная причина, по которой точечные запросы дорогие в ClickHouse, — это его разреженный первичный индекс основной семьи движков таблиц MergeTree. Этот индекс не может указывать на каждую конкретную строку данных, вместо этого он указывает на каждую N-ю строку, и системе приходится сканировать от соседней N-й строки до нужной, считывая лишние данные по пути. В сценарии с ключ-значение может быть полезно уменьшить значение N с помощью настройки index_granularity.
  • ClickHouse хранит каждую колонку в отдельном наборе файлов, поэтому, чтобы собрать одну полную строку, ему необходимо пройти через каждый из этих файлов. Их количество увеличивается линейно с количеством колонок, поэтому в сценарии с ключ-значение может быть разумно избегать использования многих колонок и поместить все ваши данные в одну колонку типа String, закодированную в каком-либо формате сериализации, таком как JSON, Protobuf или в любом формате, который имеет смысл.
  • Существует альтернативный подход, который использует Join движок таблиц вместо обычных таблиц MergeTree и функцию joinGet для извлечения данных. Он может обеспечить лучшую производительность запросов, но может иметь некоторые проблемы с удобством использования и надежностью. Вот пример использования.