СОЗДАТЬ ПРЕДСТАВЛЕНИЕ
Создает новое представление. Представления могут быть нормальными, материализованными, обновляемыми материализованными и окнами.
Нормальное представление
Синтаксис:
Нормальные представления не хранят никаких данных. Они просто выполняют чтение из другой таблицы при каждом доступе. Другими словами, нормальное представление не что иное, как сохраненный запрос. При чтении из представления этот сохраненный запрос используется как подзапрос в 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
, данные агрегируются во время вставки, но только в рамках одного пакета вставленных данных. Данные не будут дополнительно агрегироваться. Исключение составляют движки, которые самостоятельно выполняют агрегацию данных, такие как 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 alice | alice должен иметь грант 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
не указаны, используются значения по умолчанию:
SQL SECURITY
:INVOKER
для нормальных представлений иDEFINER
для материализованных представлений (настраиваемо с помощью настроек)DEFINER
:CURRENT_USER
(настраиваемо с помощью настроек)
Если представление присоединено без указанного DEFINER
/SQL SECURITY
, значение по умолчанию - SQL SECURITY NONE
для материализованного представления и SQL SECURITY INVOKER
для нормального представления.
Чтобы изменить безопасность SQL для существующего представления, используйте
Примеры
Обновляемое материализованное представление
где 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
режиме поддерживается только координированное обновление. Для некординированных используйте атомарную базу данных и запрос 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==
Оконное представление
Это экспериментальная функция, которая может измениться в несовместимые с предыдущими версии в будущих релизах. Включите использование оконных представлений и запросов 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
: Интервал "сердцебиения" в секундах, чтобы указать, что запрос на мониторинг активен.wait_for_window_view_fire_signal_timeout
: Тайм-аут для ожидания сигнала срабатывания оконного представления в обработке времени событий.
Пример
Предположим, нам нужно считать количество логов кликов каждые 10 секунд в таблице логов под названием data
, и ее структура таблицы следующая:
Сначала мы создаем оконное представление с временным интервалом 10 секунд:
Затем мы используем запрос WATCH
, чтобы получить результаты.
Когда логи вставляются в таблицу data
,
Запрос WATCH
должен напечатать результаты следующим образом:
Кроме того, мы можем прикрепить вывод к другой таблице, используя синтаксис TO
.
Дополнительные примеры можно найти среди тестов состояния ClickHouse (они называются *window_view*
там).
Использование оконного представления
Оконное представление полезно в следующих сценариях:
- Мониторинг: Агрегировать и вычислять метрики логов по времени, а затем выводить результаты в целевую таблицу. Панель мониторинга может использовать целевую таблицу в качестве исходной.
- Анализ: Автоматически агрегировать и предварительно обрабатывать данные в временном окне. Это может быть полезно при анализе большого количества логов. Предварительная обработка исключает повторные вычисления в нескольких запросах и сокращает задержку запросов.
Связанный контент
- Блог: Работа с данными временных рядов в ClickHouse
- Блог: Создание решения для мониторинга с помощью ClickHouse - Часть 2 - Трейсы
Временные представления
ClickHouse поддерживает временные представления со следующими характеристиками (соответствующими временным таблицам, где это уместно):
-
Время сессии Временное представление существует только в течение текущей сессии. Оно автоматически удаляется, когда сессия заканчивается.
-
Без базы данных Вы не можете указывать временное представление с именем базы данных. Оно существует вне баз данных (пространство имен сессии).
-
Не реплицируемые / без ON CLUSTER Временные объекты локальны для сеанса и не могут быть созданы с помощью
ON CLUSTER
. -
Разрешение имен Если временный объект (таблица или представление) имеет то же имя, что и постоянный объект, и запрос ссылается на имя без базы данных, временный объект будет использоваться.
-
Логический объект (без хранения) Временное представление хранит только текст своего
SELECT
(использует внутреннийView
для хранения). Оно не хранит данные и не может приниматьINSERT
. -
Клаузу ENGINE Вы не обязаны указывать
ENGINE
; если предоставлено какENGINE = View
, оно игнорируется/рассматривается как одно и то же логическое представление. -
Безопасность / привилегии Создание временного представления требует привилегии
CREATE TEMPORARY VIEW
, которая неявно предоставляется приCREATE VIEW
. -
SHOW CREATE Используйте
SHOW CREATE TEMPORARY VIEW view_name;
, чтобы напечатать DDL временного представления.
Синтаксис
OR REPLACE
не поддерживается для временных представлений (в соответствии с временными таблицами). Если вам нужно "заменить" временное представление, удалите его и создайте заново.
Примеры
Создайте временную исходную таблицу и временное представление поверх нее:
Показать его DDL:
Удалить его:
Запрещенные / ограничения
CREATE OR REPLACE TEMPORARY VIEW ...
→ не разрешено (используйтеDROP
+CREATE
).CREATE TEMPORARY MATERIALIZED VIEW ...
/LIVE VIEW
/WINDOW VIEW
→ не разрешено.CREATE TEMPORARY VIEW db.view AS ...
→ не разрешено (без указания базы данных).CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...
→ не разрешено (временные объекты локальны для сессии).POPULATE
,REFRESH
,TO [db.table]
, внутренние движки и все специфичные для MV конструкции → не применимо для временных представлений.
Заметки о распределенных запросах
Временное представление - это просто определение; нет данных, которые нужно передавать. Если ваше временное представление ссылается на временные таблицы (например, Memory
), их данные могут быть доставлены на удаленные серверы во время выполнения распределенного запроса так же, как работают временные таблицы.