Кэш условий запроса
Кэш условий запроса работает только тогда, когда enable_analyzer установлен на true, что является значением по умолчанию.
Многие реальные рабочие нагрузки включают повторяющиеся запросы к одним и тем же или почти одинаковым данным (например, ранее существующие данные плюс новые данные). 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, так как части являются неизменяемыми и создаются только с помощью INSERTs.
- В-третьих, фильтры являются выборочными, т.е. только относительно немногие строки удовлетворяют условию фильтра. Чем меньше строк соответствует условию фильтра, тем больше гранул будет записано с битом 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
.
Если вы хотите исследовать отдельные условия фильтра, вы можете проверить поле condition
в system.query_condition_cache
.
Обратите внимание, что поле заполняется только если запрос выполняется с включенной настройкой query_condition_cache_store_conditions_as_plaintext.
Количество попаданий и промахов кэша условий запроса с момента запуска базы данных отображается как события "QueryConditionCacheHits" и "QueryConditionCacheMisses" в системной таблице system.events.
Обе счетчики обновляются только для запросов SELECT
, которые выполняются с настройкой use_query_condition_cache = true
, другие запросы не влияют на "QueryCacheMisses".