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

Кэш Запросов

Кэш запросов позволяет выполнять SELECT запросы только один раз и обслуживать дальнейшие исполнения того же запроса непосредственно из кэша. В зависимости от типа запросов, это может существенно уменьшить задержку и потребление ресурсов сервера ClickHouse.

Основы, Дизайн и Ограничения

Кэши запросов можно рассматривать как транзакционно согласованные или несогласованные.

  • В транзакционно согласованных кэша, база данных аннулирует (отменяет) кэшированные результаты запросов, если результат SELECT запроса изменяется или потенциально изменяется. В ClickHouse операциями, которые изменяют данные, являются вставки/обновления/удаления в/из/из таблиц или слияния с помощью collapses. Транзакционно согласованный кэш особенно подходит для OLTP баз данных, например, MySQL (который удалил кэш запросов после версии 8.0) и Oracle.
  • В транзакционно несогласованных кэша, небольшие неточности в результатах запросов допускаются с допущением, что все записи в кэше имеют срок действия, по истечении которого они истекают (например, 1 минута), и что подлежащие данные изменяются незначительно в этом периоде. Этот подход в целом более подходит для OLAP баз данных. В качестве примера, когда транзакционно несогласованный кэш достаточно, рассмотрим ежечасный отчет по продажам в инструменте отчетности, который одновременно открывается несколькими пользователями. Данные о продажах изменяются, как правило, достаточно медленно, чтобы базе данных необходимо было вычислить отчет только один раз (представленный первым SELECT запросом). Последующие запросы могут обслуживаться непосредственно из кэша запросов. В этом примере разумный срок действия может составлять 30 минут.

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

Настройки Конфигурации и Использование

примечание

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

примечание

clickhouse-local выполняет только один запрос за раз. Поскольку кэширование результатов запроса не имеет смысла, кэш результатов запроса отключен в clickhouse-local.

Настройка use_query_cache может использоваться для управления тем, должен ли конкретный запрос или все запросы текущей сессии использовать кэш запросов. Например, первое выполнение запроса

сохранит результат запроса в кэше запросов. Последующие выполнения того же запроса (также с параметром use_query_cache = true) будут считывать вычисленный результат из кэша и немедленно возвращать его.

примечание

Настройка use_query_cache и все другие настройки, связанные с кэшем запросов, действуют только на отдельные SELECT операторы. В частности, результаты SELECT для представлений, созданных с помощью CREATE VIEW AS SELECT [...] SETTINGS use_query_cache = true, не кешируются, если оператор SELECT не выполняется с SETTINGS use_query_cache = true.

Способ использования кэша можно настроить более детально с помощью настроек enable_writes_to_query_cache и enable_reads_from_query_cache (по умолчанию обе true). Первая настройка управляет тем, сохраняются ли результаты запросов в кэше, в то время как вторая настройка определяет, должна ли база данных пытаться извлечь результаты запросов из кэша. Например, следующий запрос будет использовать кэш только пассивно, т.е. пытаться читать из него, но не сохранять свой результат в него:

Для максимального контроля в целом рекомендуется задавать настройки use_query_cache, enable_writes_to_query_cache и enable_reads_from_query_cache только для конкретных запросов. Также можно включить кэширование на уровне пользователя или профиля (например, через SET use_query_cache = true), но следует помнить, что все SELECT запросы могут тогда возвращать кэшированные результаты.

Кэш запросов можно очистить с помощью оператора SYSTEM DROP QUERY CACHE. Содержимое кэша запросов отображается в системной таблице system.query_cache. Количество попаданий и пропусков кэша запросов с момента запуска базы данных отображается как события "QueryCacheHits" и "QueryCacheMisses" в системной таблице system.events. Оба счетчика обновляются только для SELECT запросов, которые выполняются с настройкой use_query_cache = true, другие запросы не влияют на "QueryCacheMisses". Поле query_cache_usage в системной таблице system.query_log показывает, для каждого выполненного запроса, был ли результат запроса записан в кэш или считан из него. Асинхронные метрики "QueryCacheEntries" и "QueryCacheBytes" в системной таблице system.asynchronous_metrics показывают, сколько записей/байт в настоящее время содержит кэш запросов.

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

Результаты запросов ссылаются в кэше запросов через Абстрактное Синтаксическое Дерево (AST) их запроса. Это означает, что кэширование не зависит от регистра, например, SELECT 1 и select 1 рассматриваются как один и тот же запрос. Чтобы сделать сопоставление более естественным, все настройки на уровне запроса, связанные с кэшем запросов, удаляются из AST.

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

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

Также возможно ограничить использование кэша отдельными пользователями с помощью профилей настроек и ограничений настроек. Более конкретно, вы можете ограничить максимальное количество памяти (в байтах), которую пользователь может выделить в кэше запросов, и максимальное количество сохраняемых результатов запросов. Для этого сначала задайте параметры query_cache_max_size_in_bytes и query_cache_max_entries в профиле пользователя в users.xml, затем установите обе настройки в режим только для чтения:

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

закэшируется только если запрос выполняется дольше 5 секунд. Также возможно указать, как часто запрос должен выполняться, чтобы его результат был закэширован - для этого используйте настройку query_cache_min_query_runs.

Записи в кэше запросов становятся устаревшими после определенного времени (время жизни). По умолчанию этот период составляет 60 секунд, но можно указать другое значение на уровне сессии, профиля или запроса с помощью настройки query_cache_ttl. Кэш запросов удаляет записи "лениво", т.е. когда запись становится устаревшей, она не удаляется сразу из кэша. Вместо этого, когда новая запись должна быть вставлена в кэш запросов, база данных проверяет, достаточно ли свободного места в кэше для новой записи. Если это не так, база данных пытается удалить все устаревшие записи. Если в кэше все еще недостаточно свободного места, новая запись не вставляется.

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

Иногда полезно держать множество результатов для одного и того же запроса в кэше. Это можно достичь с помощью настройки query_cache_tag, которая выступает в роли метки (или пространства имен) для записей кэша запросов. Кэш запросов считает результаты одного и того же запроса с разными метками разными.

Пример создания трех различных записей кэша запросов для одного и того же запроса:

Чтобы удалить только записи с меткой tag из кэша запросов, вы можете использовать оператор SYSTEM DROP QUERY CACHE TAG 'tag'.

ClickHouse считывает данные из таблицы блоками по max_block_size строк. Из-за фильтрации, агрегации и т.д. блоки результатов, как правило, значительно меньше 'max_block_size', но также есть и случаи, когда они значительно больше. Настройка query_cache_squash_partial_results (включена по умолчанию) управляет тем, следует ли сжать результатные блоки (если они крошечные) или разбить их (если они большие) на блоки размером 'max_block_size' перед вставкой в кэш результатов запроса. Это уменьшает производительность записей в кэш запросов, но улучшает коэффициент сжатия записей кэша и обеспечивает более естественную гранулярность блоков, когда результаты запросов позже обслуживаются из кэша запросов.

В результате, кэш запросов хранит для каждого запроса несколько (частичных) результатных блоков. Хотя это поведение является хорошим значением по умолчанию, его можно подавить с помощью настройки query_cache_squash_partial_results.

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

Чтобы принудительно кешировать результаты запросов с недетерминированными функциями, используйте настройку query_cache_nondeterministic_function_handling.

Результаты запросов, которые включают системные таблицы (например, system.processes или information_schema.tables), по умолчанию не кешируются. Чтобы принудительно кешировать результаты запросов с системными таблицами, используйте настройку query_cache_system_table_handling.

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