Skip to main content
Тип структуры словаря cached хранит словарь в кэше с фиксированным количеством ячеек. Эти ячейки содержат часто используемые элементы. Ключ словаря имеет тип UInt64. При обращении к словарю сначала выполняется поиск в кэше. Для каждого блока данных все ключи, которые не найдены в кэше или являются устаревшими, запрашиваются из источника с помощью SELECT attrs... FROM db.table WHERE id IN (k1, k2, ...). Полученные данные затем записываются в кэш. Это относится к поиску ключа — dictGet и другим функциям работы со словарями. Чтение словаря как таблицы через SELECT ... FROM <dictionary> работает иначе: поскольку кэш не хранит сведений о том, какие ключи существуют, при чтении перечисляются только те ячейки, которые в этот момент находятся в кэше и содержат значение, а условие WHERE по ключу — это обычный фильтр по этим ячейкам, а не список ключей для загрузки. Ключ, которого нет в кэше, таким способом обнаружить нельзя, что бы ни было указано в WHERE. Ключ, который был запрошен, но не найден в источнике, также не виден: кэш запоминает промах как ячейку со значением по умолчанию, а при чтении как таблицы такие ячейки пропускаются. Находящиеся в кэше ячейки тоже не избавлены от обращений к источнику: устаревшая ячейка читается по тому же пути, что и dictGet, поэтому она повторно запрашивается из источника — синхронно или асинхронно, если включен параметр allow_read_expired_keys.
Итак, словарь cache предназначен для использования через функции словаря. Если требуется, чтобы поиск произвольных ключей всегда доходил до источника, используйте dictGet со структурой direct, которая обращается к источнику при каждом поиске и ничего не кэширует. Обратите внимание, что чтение словаря direct как таблицы также не является выборкой по ключам: SELECT ... FROM <dictionary> WHERE key IN (...) загружает весь источник и фильтрует данные уже после этого, поскольку ClickHouse не проталкивает фильтр по ключу в словарь. Чтобы читать словарь как таблицу, используйте структуру, хранящую его целиком, например flat или hashed. Если ключи не найдены в словаре, создается задача обновления кэша и добавляется в очередь обновлений. Параметрами очереди обновлений можно управлять с помощью настроек max_update_queue_size, update_queue_push_timeout_milliseconds, query_wait_timeout_milliseconds, max_threads_for_updates. Для словарей cache можно задать срок действия данных в кэше — lifetime. Если с момента загрузки данных в ячейку прошло больше времени, чем lifetime, значение ячейки не используется, и ключ считается устаревшим. При следующем обращении этот ключ будет запрошен повторно. Это поведение можно настроить с помощью параметра allow_read_expired_keys. Это наименее эффективный из всех способов хранения словарей. Производительность кэша сильно зависит от правильности настроек и сценария использования. Словарь типа cache показывает хорошую производительность только при достаточно высокой доле попаданий в кэш (рекомендуется 99% и выше). Среднюю долю попаданий можно посмотреть в таблице system.dictionaries. Если параметр allow_read_expired_keys установлен в 1 (по умолчанию — 0), словарь может поддерживать асинхронные обновления. Если клиент запрашивает ключи и все они есть в кэше, но некоторые из них устарели, словарь вернет клиенту устаревшие ключи и асинхронно запросит их из источника. Чтобы повысить производительность кэша, используйте подзапрос с LIMIT и вызывайте функцию вне словаря. Поддерживаются все типы источников. Пример настроек:

Задайте достаточно большой размер кэша. Чтобы подобрать количество ячеек, нужно поэкспериментировать:
  1. Задайте некоторое значение.
  2. Выполняйте запросы, пока кэш полностью не заполнится.
  3. Оцените потребление памяти с помощью таблицы system.dictionaries.
  4. Увеличивайте или уменьшайте количество ячеек, пока не будет достигнут требуемый уровень потребления памяти.
Не рекомендуется использовать ClickHouse в качестве источника для этой структуры. Поиск по словарю требует случайных точечных чтений, а ClickHouse не оптимизирован под такой шаблон доступа.
Последнее изменение 24 сентября 2026 г.