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

CREATE VIEW

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

Обычное представление

Синтаксис:

Обычные представления не хранят никаких данных. Они просто выполняют чтение из другой таблицы при каждом доступе. Иными словами, обычное представление — это не что иное, как сохранённый запрос. При чтении из представления этот сохранённый запрос используется как подзапрос в предложении FROM.

Например, предположим, что вы создали представление:

и написали запрос:

Этот запрос полностью эквивалентен использованию подзапроса:

Параметризованное представление

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

Выше создаётся представление для таблицы, которое может быть использовано как табличная функция, подставив параметры, как показано ниже.

Материализованное представление

подсказка

Здесь содержится пошаговое руководство по использованию материализованных представлений.

Материализованные представления хранят данные, преобразованные соответствующим запросом SELECT.

При создании материализованного представления без указания TO [db].[table], необходимо указать ENGINE — движок таблицы для хранения данных.

При создании материализованного представления с использованием TO [db].[table], нельзя использовать POPULATE.

Материализованное представление реализовано следующим образом: при вставке данных в таблицу, указанную в SELECT, часть вставленных данных преобразуется этим запросом SELECT, и результат вставляется в представление.

примечание

Материализованные представления в ClickHouse используют имена столбцов вместо порядка столбцов во время вставки в целевую таблицу. Если некоторые имена столбцов отсутствуют в результате запроса SELECT, ClickHouse использует значение по умолчанию, даже если столбец не является Nullable. Безопасной практикой будет добавление алиасов для каждого столбца при использовании материализованных представлений.

Материализованные представления в ClickHouse реализованы больше как триггеры вставки. Если в запросе представления есть агрегация, она применяется только к партии свежевставленных данных. Любые изменения существующих данных исходной таблицы (например, обновление, удаление, удаление раздела и т.д.) не влияют на материализованное представление.

Материализованные представления в ClickHouse не обладают детерминированным поведением в случае ошибок. Это означает, что блоки, которые уже были записаны, будут сохранены в целевой таблице, но все блоки после ошибки не будут записаны.

По умолчанию, если вставка в одно из представлений не удалась, запрос INSERT также не удастся, и некоторые блоки могут не быть записаны в целевую таблицу. Это можно изменить, используя настройку materialized_views_ignore_errors (её нужно установить для запроса INSERT), если установить materialized_views_ignore_errors=true, то любые ошибки при записи в представления будут игнорироваться и все блоки будут записаны в целевую таблицу.

Также обратите внимание, что materialized_views_ignore_errors установлено на true по умолчанию для таблиц system.*_log.

Если вы указываете POPULATE, существующие данные таблицы вставляются в представление при его создании, как будто выполняется CREATE TABLE ... AS SELECT .... В противном случае запрос содержит только данные, вставленные в таблицу после создания представления. Мы не рекомендуем использовать POPULATE, так как данные, вставленные в таблицу во время создания представления, не будут вставлены в него.

примечание

Учитывая, что POPULATE работает как CREATE TABLE ... AS SELECT ..., он имеет ограничения:

  • Не поддерживается с реплицируемой базой данных
  • Не поддерживается в ClickHouse cloud

Вместо этого можно использовать отдельный INSERT ... SELECT.

Запрос SELECT может содержать DISTINCT, GROUP BY, ORDER BY, LIMIT. Обратите внимание, что соответствующие преобразования выполняются независимо для каждого блока вставленных данных. Например, если установлен GROUP BY, данные агрегируются при вставке, но только в пределах одного пакета вставленных данных. Данные не будут дополнительно агрегироваться. Исключение составляет использование движка ENGINE, который самостоятельно выполняет агрегацию данных, например SummingMergeTree.

Выполнение запросов ALTER на материализованных представлениях имеет ограничения, например, нельзя обновить запрос SELECT, что может быть неудобно. Если материализованное представление использует конструкцию TO [db.]name, вы можете DETACH представить, выполнить ALTER для целевой таблицы и затем ATTACH ранее отсоединенное (DETACH) представление.

Обратите внимание, что на материализованное представление влияет настройка optimize_on_insert. Данные сливаются перед вставкой в представление.

Представления выглядят так же, как и обычные таблицы. Например, они перечислены в результате запроса SHOW TABLES.

Чтобы удалить представление, используйте DROP VIEW. Однако DROP TABLE работает и для представлений.

Безопасность SQL

DEFINER и SQL SECURITY позволяют указать, какого пользователя ClickHouse использовать при выполнении базового запроса представления. SQL SECURITY имеет три допустимых значения: DEFINER, INVOKER или NONE. Вы можете указать любого существующего пользователя или CURRENT_USER в предложении DEFINER.

Следующая таблица объяснит, какие права требуются от какого пользователя для того, чтобы выбрать данные из представления. Обратите внимание, что независимо от опции безопасности SQL в каждом случае требуется наличие GRANT SELECT ON <view> для чтения из него.

Опция безопасности SQLПредставлениеМатериализованное представление
DEFINER alicealice должна иметь грант SELECT для исходной таблицы представления.alice должна иметь грант SELECT для исходной таблицы представления и грант INSERT для целевой таблицы представления.
INVOKERПользователь должен иметь грант SELECT для исходной таблицы представления.SQL SECURITY INVOKER не может быть указан для материализованных представлений.
NONE--
примечание

SQL SECURITY NONE — это устаревшая опция. Любой пользователь с правами на создание представлений с SQL SECURITY NONE сможет выполнить любой произвольный запрос. Таким образом, требуется наличие GRANT ALLOW SQL SECURITY NONE TO <user> для создания представления с этой опцией.

Если DEFINER/SQL SECURITY не указаны, используются значения по умолчанию:

Если представление подключено без указания DEFINER/SQL SECURITY, значение по умолчанию — это SQL SECURITY NONE для материализованного представления и SQL SECURITY INVOKER для обычного представления.

Чтобы изменить безопасность SQL для существующего представления, используйте:

Примеры

Live-представление

Deprecated feature

Эта функция устарела и будет удалена в будущем.

Для вашего удобства старая документация находится здесь

Обновляемое материализованное представление

где interval — это последовательность простых интервалов:

периодически выполняет соответствующий запрос и сохраняет его результат в таблице.

  • Если в запросе указано APPEND, каждое обновление добавляет строки в таблицу без удаления существующих строк. Вставка не является атомарной, как и обычный INSERT SELECT.
  • В противном случае каждое обновление атомарно заменяет предыдущие данные в таблице.

Различия от обычных необновляемых материализованных представлений:

  • Нет триггера вставки. Т.е. когда новые данные вставляются в таблицу, указанную в SELECT, они НЕ автоматически попадают в обновляемое материализованное представление. Периодическое обновление выполняет весь запрос.
  • Нет ограничений на запрос SELECT. Табличные функции (например, url()), представления, UNION, JOIN разрешены.
примечание

Настройки в части запроса REFRESH ... SETTINGS являются настройками обновления (например, refresh_retries), отличными от обычных настроек (например, max_threads). Обычные настройки можно указать, используя SETTINGS в конце запроса.

Расписание обновления

Пример расписания обновления:

RANDOMIZE FOR случайным образом корректирует время каждого обновления, напр.:

В одно и то же время для данного представления может выполняться не более одного обновления. Например, если представление с REFRESH EVERY 1 MINUTE обновляется 2 минуты, оно будет обновляться каждые 2 минуты. Если потом оно станет быстрее и начнёт обновляться за 10 секунд, оно вернется к обновлению каждую минуту. (В частности, оно не будет обновляться каждые 10 секунд, чтобы догнать отставание по пропущенным обновлениям — такого отставания нет.)

Кроме того, обновление начинается сразу после создания материализованного представления, если в запросе CREATE не указано EMPTY. Если EMPTY указано, первое обновление происходит по расписанию.

В реплицируемых базах данных

Если обновляемое материализованное представление находится в реплицируемой базе данных, реплики координируются друг с другом таким образом, чтобы только одна реплика выполняла обновление в каждое запланированное время. Требуется движок таблицы ReplicatedMergeTree, чтобы все реплики видели данные, полученные в результате обновления.

В режиме APPEND координация может быть отключена, используя SETTINGS all_replicas = 1. Это заставляет реплики выполнять обновления независимо друг от друга. В этом случае ReplicatedMergeTree не требуется.

В нет режиме APPEND поддерживается только координированное обновление. Для некоординированного используется база данных Atomic и запрос CREATE ... ON CLUSTER для создания обновляемых материализованных представлений на всех репликах.

Координация осуществляется через Keeper. Путь znode определяется настройкой сервера default_replica_path.

Зависимости

DEPENDS ON синхронизирует обновления разных таблиц. Например, предположим, что существует цепочка из двух обновляемых материализованных представлений:

Без DEPENDS ON оба представления начнут обновление в полночь, и destination, как правило, будет видеть вчерашние данные в source. Если мы добавим зависимость:

тогда обновление destination начнёт выполняться только после завершения обновления source за этот день, так что destination будет основано на свежих данных.

Или, тот же результат можно достичь с помощью:

где 1 HOUR может быть любым интервалом, меньшим, чем период обновления source. Зависимая таблица не будет обновляться чаще, чем любая из её зависимостей. Это действительный способ установить цепочку обновляемых представлений, не указывая реальный период обновления больше одного раза.

Ещё несколько примеров:

  • REFRESH EVERY 1 DAY OFFSET 10 MINUTE (destination) зависит от REFRESH EVERY 1 DAY (source)
    Если обновление source занимает больше 10 минут, destination будет ждать его.
  • REFRESH EVERY 1 DAY OFFSET 1 HOUR зависит от REFRESH EVERY 1 DAY OFFSET 23 HOUR
    Похоже на вышеприведённое, хотя соответствующие обновления происходят в разные календарные дни. Обновление destination на день X+1 будет ждать завершения обновления source за день X (если оно занимает более 2 часов).
  • REFRESH EVERY 2 HOUR зависит от REFRESH EVERY 1 HOUR
    2-часовое обновление происходит после 1-часового обновления каждые два часа, например, после полуночи, затем после 2 часов ночи и т.д.
  • REFRESH EVERY 1 MINUTE зависит от REFRESH EVERY 2 HOUR
    REFRESH AFTER 1 MINUTE зависит от REFRESH EVERY 2 HOUR
    REFRESH AFTER 1 MINUTE зависит от REFRESH AFTER 2 HOUR
    destination обновляется один раз после каждого обновления source, то есть каждые 2 часа. Фактически 1 MINUTE игнорируется.
  • REFRESH AFTER 1 HOUR зависит от REFRESH AFTER 1 HOUR
    В настоящее время это не рекомендуется.
примечание

DEPENDS ON работает только между обновляемыми материализованными представлениями. Указание обычной таблицы в списке DEPENDS ON приведёт к тому, что представление никогда не будет обновляться (зависимости могут быть удалены с помощью ALTER, см. ниже).

Настройки

Доступные настройки обновления:

  • refresh_retries - сколько раз повторить попытку, если запрос обновления завершится с исключением. Если все попытки не удачны, пропустить до следующего запланированного времени обновления. 0 означает отсутствие повторов, -1 означает бесконечные повторы. По умолчанию: 0.
  • refresh_retry_initial_backoff_ms - задержка перед первой попыткой повтора, если refresh_retries не равен нулю. Каждая последующая попытка повтора удваивает задержку, вплоть до refresh_retry_max_backoff_ms. По умолчанию: 100 мс.
  • refresh_retry_max_backoff_ms - ограничение на экспоненциальный рост задержки между попытками обновления. По умолчанию: 60000 мс (1 минута).

Изменение параметров обновления

Чтобы изменить параметры обновления:

примечание

Это заменяет все параметры обновления одновременно: расписание, зависимости, настройки и добавление (APPEND). Например, если таблица имела DEPENDS ON, выполнение MODIFY REFRESH без указания DEPENDS ON удалит зависимости.

Другие операции

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

Для ручной остановки, запуска, вызова или отмены обновлений используйте SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW.

Чтобы дождаться завершения обновления, используйте SYSTEM WAIT VIEW. В частности, это полезно для ожидания начального обновления после создания представления.

примечание

Интересный факт: запрос обновления может читать из представления, которое обновляется, видя до-обновлённую версию данных. Это значит, что вы можете реализовать Игру Жизни Конуэя: https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==

Оконное представление

Experimental feature. Learn more.
Not supported in ClickHouse Cloud
к сведению

Это экспериментальная функция, которая в будущем может измениться и стать несовместимой с предыдущими версиями. Включите использование оконных представлений и запроса WATCH, используя настройку allow_experimental_window_view. Введите команду set allow_experimental_window_view = 1.

Оконное представление может агрегировать данные по временным окнам и выводить результаты, когда окно готово к срабатыванию. Оно хранит результаты частичной агрегации во внутренней (или указанной) таблице, чтобы уменьшить задержку, и может отправлять результат обработки в указанную таблицу или отправлять уведомления, используя запрос WATCH.

Создание оконного представления похоже на создание MATERIALIZED VIEW. Оконному представлению нужен внутренний движок хранения для хранения промежуточных данных. Внутреннее хранилище может быть указано с использованием предложения INNER ENGINE, по умолчанию оконное представление будет использовать AggregatingMergeTree в качестве внутреннего движка.

При создании оконного представления без TO [db].[table], необходимо указать ENGINE — движок таблицы для хранения данных.

Временные оконные функции

Временные оконные функции используются для получения нижней и верхней границы окна записей. Оконное представление должно использоваться с временной оконной функцией.

ВРЕМЕННЫЕ АТРИБУТЫ

Оконное представление поддерживает время обработки и время события.

Время обработки позволяет оконному представлению выдавать результаты на основе времени локальной машины и используется по умолчанию. Это самое простое понятие времени, но оно не обеспечивает детерминированности. Атрибут времени обработки может быть определён путём установки time_attr временной оконной функции в столбец таблицы или использованием функции now(). Следующий запрос создаёт оконное представление с временем обработки.

Время события — это время, когда каждое отдельное событие произошло на устройстве, его создавшем. Это время обычно встроено в записи при их создании. Обработка времени события позволяет получать одинаковые результаты даже в случае несинхронных или поздних событий. Оконное представление поддерживает обработку времени события, используя синтаксис WATERMARK.

Оконное представление предлагает три стратегии водяных знаков:

  • STRICTLY_ASCENDING: Выдает водяной знак максимального наблюдаемого на текущий момент времени. Строки, у которых временная метка меньше максимальной временной метки, не считаются поздними.
  • ASCENDING: Выдает водяной знак максимального наблюдаемого на текущий момент времени минус 1. Строки, у которых временная метка равна и меньше максимальной временной метки, не считаются поздними.
  • BOUNDED: WATERMARK=INTERVAL. Выдает водяные знаки, которые являются максимальной наблюдаемой временной меткой за вычетом указанной задержки.

Следующие запросы являются примерами создания оконного представления с помощью WATERMARK:

По умолчанию окно срабатывает, когда поступает водяной знак, и элементы, которые пришли после водяного знака, отбрасываются. Оконное представление поддерживает обработку поздних событий, настроив ALLOWED_LATENESS=INTERVAL. Пример обработки задержек:

Обратите внимание, что элементы, сгенерированные поздним срабатыванием, следует рассматривать как обновленные результаты предыдущего вычисления. Вместо срабатывания в конце окон, оконное представление будет срабатывать немедленно, когда прибудет позднее событие. Таким образом, для одного и того же окна будет получено несколько результатов. Пользователи должны учитывать эти дублированные результаты или удалять их.

Вы можете изменить запрос SELECT, указанный в оконном представлении, с помощью оператора ALTER TABLE ... MODIFY QUERY. Структура данных, полученная в новом запросе SELECT, должна быть такой же, как и в исходном запросе SELECT, при использовании или без использования предложения TO [db.]name. Обратите внимание, что данные в текущем окне будут утеряны, поскольку промежуточное состояние не может быть повторно использовано.

Мониторинг новых окон

Оконное представление поддерживает запрос WATCH для мониторинга изменений или использование синтаксиса TO для вывода результатов в таблицу.

Запрос WATCH действует аналогично LIVE VIEW. Можно указать LIMIT, чтобы задать количество обновлений, которые необходимо получить перед завершением запроса. Опция EVENTS может быть использована для получения краткой формы запроса WATCH, где вместо результата запроса вы получите просто последние данные водяного знака запроса.

Настройки

  • window_view_clean_interval: Интервал очистки оконного представления в секундах для освобождения устаревших данных. Система сохранит окна, которые не были полностью сработаны в соответствии с системным временем или конфигурацией WATERMARK, а остальные данные будут удалены.
  • window_view_heartbeat_interval: Интервал сердцебиения в секундах, чтобы указать, что запрос наблюдения (watch) активен.
  • wait_for_window_view_fire_signal_timeout: Таймаут ожидания сигнала срабатывания оконного представления при обработке времени события.

Пример

Предположим, нам нужно подсчитать количество кликов по логам в интервале 10 секунд в таблице логов data, структура которой:

Сначала мы создадим оконное представление с оконным интервалом в 10 секунд:

Затем используем запрос WATCH, чтобы получить результаты.

Когда логи вставляются в таблицу data,

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

В качестве альтернативы мы можем связать вывод с другой таблицей, используя синтаксис TO.

Дополнительные примеры можно найти среди тестов состояния ClickHouse (они названы *window_view*).

Использование оконных представлений

Оконные представления полезны в следующих сценариях:

  • Мониторинг: Агрегация и вычисление метрик журналов по времени и вывод результатов в целевую таблицу. Панель мониторинга может использовать целевую таблицу как источник данных.
  • Анализ: Автоматическая агрегация и предварительная обработка данных во временном окне. Это может быть полезно при анализе большого количества журналов. Предварительная обработка устраняет повторные вычисления в нескольких запросах и уменьшает задержку запроса.