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

Производительность запросов временных рядов

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

Оптимизация ключей ORDER BY

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

Давайте создадим другую версию таблицы, которая имеет те же типы столбцов, что и 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

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

Создание материализованного представления

Мы можем создать следующее материализованное представление:

Заполнение целевой таблицы

Эта целевая таблица будет заполняться только при добавлении новых записей в таблицу wikistat, поэтому нам нужно сделать немного фоновской подкачки.

Самый простой способ сделать это — использовать оператор INSERT INTO SELECT для вставки прямо в целевую таблицу материализованного представления с помощью запроса SELECT представления (трансформации):

В зависимости от кардинальности исходного набора данных (у нас 1 миллиард строк!), этот подход может потреблять много памяти. В качестве альтернативы вы можете использовать вариант, который требует минимальных затрат памяти:

  • Создание временной таблицы с движком Null
  • Подключение копии обычно используемого материализованного представления к этой временной таблице
  • Использование запроса INSERT INTO SELECT, копируя все данные из исходного набора данных во временную таблицу
  • Удаление временной таблицы и временного материализованного представления.

С помощью этого подхода строки из исходного набора данных копируются блоками во временную таблицу (которая не хранит ни одной из этих строк), и для каждого блока строк вычисляется частичное состояние, которое записывается в целевую таблицу, где эти состояния постепенно объединяются в фоновом режиме.

Далее мы создадим материализованное представление для чтения из wikistat_backfill и записи в wikistat_top

И наконец, мы заполним wikistat_backfill из начальной таблицы wikistat:

После завершения этого запроса мы можем удалить таблицу подкачки и материализованное представление:

Теперь мы можем выполнять запрос к материализованному представлению вместо оригинальной таблицы:

Улучшение производительности здесьdramatic. Раньше на расчет ответа на этот запрос уходило чуть более 2 секунд, теперь это занимает всего 4 миллисекунды.