Перейти к основному содержанию
В этой статье описано, как работает ленивая материализация и какое место она занимает в более широком стеке оптимизаций ввода-вывода в ClickHouse. В ней также приводится реальный пример, показывающий, как ленивая материализация повышает производительность запросов.
Доступно с версии 25.4Ленивая материализация была добавлена в ClickHouse версии 25.4 и включена по умолчанию.

Обзор

За годы развития ClickHouse внедрил ряд многоуровневых оптимизаций, позволяющих существенно сократить I/O. Эти методы лежат в основе его скорости и эффективности: Хотя перечисленные выше оптимизации I/O могут существенно сократить объём читаемых данных, они всё же исходят из того, что все столбцы для строк, прошедших условие WHERE, должны быть загружены до выполнения таких операций, как сортировка, агрегация или LIMIT. Но что, если некоторые столбцы не нужны до более позднего этапа, или часть данных, несмотря на прохождение условия WHERE, вообще так и не потребуется? Здесь на помощь приходит ленивая материализация. Это независимое улучшение, которое дополняет стек оптимизаций I/O:
  • Индексирование вместе с PREWHERE гарантирует, что обрабатываются только строки, соответствующие фильтрам по столбцам в условии WHERE.
  • Ленивая материализация развивает эту идею, откладывая чтение столбцов до момента, когда они действительно потребуются по плану выполнения запроса. Даже после фильтрации сразу загружаются только те столбцы, которые нужны для следующей операции — например, сортировки. Чтение остальных откладывается и, благодаря LIMIT, часто выполняется лишь частично — ровно настолько, насколько это нужно для получения итогового результата. Это делает ленивую материализацию особенно эффективной для запросов Top N, где для итогового результата может понадобиться лишь несколько строк из некоторых, нередко больших, столбцов.

Подробный пример

Мы настоятельно рекомендуем статью в блоге “ClickHouse gets lazier (and faster): Introducing lazy materialization” для более глубокого знакомства с ленивой материализацией. Пример ниже взят из этой статьи и приведён здесь, чтобы показать, как запрос к ClickHouse может выполняться не 219 секунд, а всего 139 миллисекунд (ускорение в 1576 раз) благодаря ленивой материализации. Чтобы использовать преимущества индексирования и PREWHERE, в запросе должны быть фильтры: по столбцам первичного ключа для индексирования и по любым столбцам для PREWHERE. Ленивая материализация хорошо сочетается с этими механизмами, но, в отличие от других упомянутых выше оптимизаций, может также ускорять запросы вообще без фильтров по столбцам. Рассмотрим следующий запрос, который находит отзывы Amazon с наибольшим числом полезных голосов независимо от даты, продукта, оценки или статуса верификации и возвращает 3 лучших вместе с их названием, заголовком и полным текстом. Сначала выполним запрос (с холодными кэшами файловой системы) при отключённой ленивой материализации (с использованием query_plan_optimize_lazy_materialization):
Query
Response
Затем запрос снова выполняется (опять с холодным файловым кэшем), но на этот раз при включенной ленивой материализации:
Query
Обычно не нужно явно задавать query_plan_optimize_lazy_materialization = true, чтобы воспользоваться преимуществами ленивой материализации. Она включена по умолчанию.
Response
Сравним производительность при отключенной и включенной ленивой материализации:

Как проверить ленивую материализацию в плане выполнения запроса

Для предыдущего запроса использование ленивой материализации можно увидеть, изучив его логический план выполнения с помощью оператора EXPLAIN:
Вы можете читать план операторов снизу вверх и заметить, что ClickHouse откладывает чтение трёх крупных столбцов типа String до выполнения сортировки и применения ограничения.
Последнее изменение 2 июля 2026 г.