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

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

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

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

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

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