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

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

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

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

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

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