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

Кэш условий запросов

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

Кэш условий запросов предоставляет элегантное решение обеих проблем. Он основан на идее, что оценка условия фильтра (например, WHERE col = 'xyz') на одних и тех же данных всегда будет приводить к одним и тем же результатам. Более конкретно, кэш условий запросов запоминает для каждого оцененного фильтра и каждой гранулы (блок из 8192 строк по умолчанию), если ни одна строка в грануле не удовлетворяет условию фильтра. Информация записывается в виде одного бита: 0 указывает на то, что ни одна строка не соответствует фильтру, тогда как 1 означает, что как минимум одна подходящая строка существует. В первом случае ClickHouse может пропустить соответствующую гранулу во время оценки фильтра, во втором случае гранула должна быть загружена и оценена.

Кэш условий запросов эффективен, если выполнены три предварительных условия:

  • Первое, рабочая нагрузка должна многократно оценивать одни и те же условия фильтров. Это происходит естественным образом, если запрос повторяется несколько раз, но также может произойти, если два запроса используют одни и те же фильтры, например, SELECT product FROM products WHERE quality > 3 и SELECT vendor, count() FROM products WHERE quality > 3.
  • Второе, большая часть данных неизменяемая, т.е. не меняется между запросами. Это обычно верно в ClickHouse, поскольку части являются неизменяемыми и создаются только с помощью INSERT.
  • Третье, фильтры должны быть селективными, т.е. только относительно небольшое количество строк удовлетворяет условию фильтра. Чем меньше строк соответствует условию фильтра, тем больше гранул будет записано с битом 0 (неподходящие строки), и тем больше данных может быть "обрезано" из последующих оценок фильтров.

Потребление памяти

Поскольку кэш условий запросов хранит только один бит на условие фильтра и гранулу, он потребляет очень мало памяти. Максимальный размер кэша условий запросов можно настроить с помощью настроек сервера query_condition_cache_size (по умолчанию: 100 МБ). Размер кэша в 100 МБ соответствует 100 * 1024 * 1024 * 8 = 838,860,800 записям. Поскольку каждая запись представляет собой метку (8192 строки по умолчанию), кэш может охватывать до 6,871,947,673,600 (6.8 триллионов) строк одного столбца. На практике фильтры оцениваются более чем по одному столбцу, поэтому это число нужно делить на количество отфильтрованных столбцов.

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

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

Например, первое выполнение запроса

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

Администрирование

Кэш условий запросов не сохраняется между перезапусками ClickHouse.

Чтобы очистить кэш условий запросов, выполните SYSTEM DROP QUERY CONDITION CACHE.

Содержимое кэша отображается в системной таблице system.query_condition_cache. Чтобы рассчитать текущий размер кэша условий запросов в МБ, выполните SELECT formatReadableSize(sum(entry_size)) FROM system.query_condition_cache.

Количество попаданий и промахов кэша условий запросов с момента запуска базы данных отображается как события "QueryConditionCacheHits" и "QueryConditionCacheMisses" в системной таблице system.events. Обе счетчики обновляются только для SELECT запросов, которые выполняются с настройкой use_query_condition_cache = true, другие запросы не влияют на "QueryCacheMisses".