Перейти к основному содержанию
После оптимизации хранения следующий шаг — повысить производительность запросов. В этом разделе рассматриваются два ключевых подхода: оптимизация ключей ORDER BY и использование materialized views. Мы увидим, как эти подходы позволяют сократить время выполнения запросов с секунд до миллисекунд.

Оптимизируйте ключи ORDER BY

Прежде чем переходить к другим оптимизациям, следует оптимизировать ключи сортировки, чтобы ClickHouse работал максимально быстро. Выбор подходящего ключа во многом зависит от того, какие запросы вы собираетесь выполнять. Предположим, что в большинстве наших запросов фильтрация идет по столбцам project и subproject. В этом случае их стоит добавить в ключ сортировки, а также столбец time, поскольку запросы выполняются и по времени. Давайте создадим ещё одну версию таблицы с теми же типами столбцов, что и у wikistat, но с сортировкой по (project, subproject, time).
Давайте теперь сравним несколько запросов, чтобы понять, насколько выражение в ключе сортировки влияет на производительность. Обратите внимание: мы не применяли предыдущие оптимизации типов данных и кодеков, поэтому все различия в производительности запросов обусловлены только порядком сортировки.
Запрос(time)(project, subproject, time)
2.381 с1.660 с
2.148 с0.058 с
2.192 с0.012 с
2.968 с0.010 с

Materialized views

Еще один вариант — использовать materialized views для агрегации и хранения результатов часто выполняемых запросов. Вместо исходной таблицы можно обращаться к этим результатам. Предположим, что в нашем случае следующий запрос выполняется довольно часто:

Создание materialized view

Можно создать следующую materialized view:

Дозагрузка целевой таблицы

Эта целевая таблица будет заполняться только при вставке новых записей в таблицу wikistat, поэтому нужно выполнить дозагрузку. Проще всего сделать это с помощью оператора INSERT INTO SELECT: выполнить вставку напрямую в целевую таблицу materialized view, используя запрос SELECT этого представления (преобразование):
В зависимости от мощности исходного набора данных (у нас 1 миллиард строк!) этот подход может требовать много памяти. В качестве альтернативы можно использовать вариант, требующий минимального объема памяти:
  • Создание временной таблицы с движком таблицы Null
  • Подключение копии обычно используемого materialized view к этой временной таблице
  • Использование запроса INSERT INTO SELECT для копирования всех данных из исходного набора данных в эту временную таблицу
  • Удаление временной таблицы и временного materialized view.
При таком подходе строки из исходного набора данных поблочно копируются во временную таблицу (которая не хранит ни одну из них), и для каждого блока строк вычисляется частичное состояние и записывается в целевую таблицу, где эти состояния инкрементально объединяются в фоновом режиме.
Далее создадим materialized view, которая будет читать из wikistat_backfill и записывать в wikistat_top
И наконец, мы заполним wikistat_backfill данными из исходной таблицы wikistat:
После завершения этого запроса можно удалить таблицу дозагрузки и materialized view:
Теперь мы можем выполнять запросы к materialized view, а не к исходной таблице:
Прирост производительности здесь впечатляющий. Раньше на вычисление ответа на этот запрос уходило чуть больше 2 секунд, а теперь — всего 4 миллисекунды.
Последнее изменение 10 июня 2026 г.