СОЗДАТЬ 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 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 часа происходит после обновления каждый час, например, после обновления в полночь и затем после обновления в 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*
там).
Использование оконного представления
Оконное представление полезно в следующих сценариях:
- Мониторинг: Агрегировать и рассчитывать метрики журналов по времени и выводить результаты в целевую таблицу. Приборная панель может использовать целевую таблицу в качестве исходной таблицы.
- Анализ: Автоматически агрегировать и предварительно обрабатывать данные в временном окне. Это может быть полезно при анализе большого количества журналов. Предварительная обработка избавляет от повторных вычислений в нескольких запросах и снижает задержку запроса.