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