--- toc_priority: 37 toc_title: "\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435" --- # CREATE VIEW {#create-view} Создаёт представление. Представления бывают двух видов - обычные и материализованные (MATERIALIZED). ## Обычные представления {#normal} ``` sql CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER] AS SELECT ... ``` Обычные представления не хранят никаких данных, они выполняют чтение данных из другой таблицы при каждом доступе. Другими словами, обычное представление — это не что иное, как сохраненный запрос. При чтении данных из представления этот сохраненный запрос используется как подзапрос в секции [FROM](../../../sql-reference/statements/select/from.md). Для примера, пусть вы создали представление: ``` sql CREATE VIEW view AS SELECT ... ``` и написали запрос: ``` sql SELECT a, b, c FROM view ``` Этот запрос полностью эквивалентен использованию подзапроса: ``` sql SELECT a, b, c FROM (SELECT ...) ``` ## Материализованные представления {#materialized} ``` sql CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER] [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT ... ``` Материализованные (MATERIALIZED) представления хранят данные, преобразованные соответствующим запросом [SELECT](../../../sql-reference/statements/select/index.md). При создании материализованного представления без использования `TO [db].[table]`, нужно обязательно указать `ENGINE` - движок таблицы для хранения данных. При создании материализованного представления с испольованием `TO [db].[table]`, нельзя указывать `POPULATE`. Материализованное представление устроено следующим образом: при вставке данных в таблицу, указанную в SELECT-е, кусок вставляемых данных преобразуется этим запросом SELECT, и полученный результат вставляется в представление. !!! important "Важно" Материализованные представления в ClickHouse больше похожи на `after insert` триггеры. Если в запросе материализованного представления есть агрегирование, оно применяется только к вставляемому блоку записей. Любые изменения существующих данных исходной таблицы (например обновление, удаление, удаление раздела и т.д.) не изменяют материализованное представление. Если указано `POPULATE`, то при создании представления, в него будут вставлены имеющиеся данные таблицы, как если бы был сделан запрос `CREATE TABLE ... AS SELECT ...` . Иначе, представление будет содержать только данные, вставляемые в таблицу после создания представления. Не рекомендуется использовать POPULATE, так как вставляемые в таблицу данные во время создания представления, не попадут в него. Запрос `SELECT` может содержать `DISTINCT`, `GROUP BY`, `ORDER BY`, `LIMIT`… Следует иметь ввиду, что соответствующие преобразования будут выполняться независимо, на каждый блок вставляемых данных. Например, при наличии `GROUP BY`, данные будут агрегироваться при вставке, но только в рамках одной пачки вставляемых данных. Далее, данные не будут доагрегированы. Исключение - использование ENGINE, производящего агрегацию данных самостоятельно, например, `SummingMergeTree`. Недоработано выполнение запросов `ALTER` над материализованными представлениями, поэтому они могут быть неудобными для использования. Если материализованное представление использует конструкцию `TO [db.]name`, то можно выполнить `DETACH` представления, `ALTER` для целевой таблицы и последующий `ATTACH` ранее отсоединенного (`DETACH`) представления. Обратите внимание, что работа материализованного представления находится под влиянием настройки [optimize_on_insert](../../../operations/settings/settings.md#optimize-on-insert). Перед вставкой данных в таблицу происходит их слияние. Представления выглядят так же, как обычные таблицы. Например, они перечисляются в результате запроса `SHOW TABLES`. Отсутствует отдельный запрос для удаления представлений. Чтобы удалить представление, следует использовать `DROP TABLE`. ## Живые представления (экспериментальные) {#live-view} !!! important "Важно" Представления `LIVE VIEW` являются экспериментальной возможностью. Их использование может повлечь потерю совместимости в будущих версиях. Чтобы использовать `LIVE VIEW` и запросы `WATCH`, включите настройку `set allow_experimental_live_view = 1`. ```sql CREATE LIVE VIEW [IF NOT EXISTS] [db.]table_name [WITH [TIMEOUT [value_in_sec] [AND]] [REFRESH [value_in_sec]]] AS SELECT ... ``` Живое представление (`LIVE VIEW`) хранит результат запроса [SELECT](../../../sql-reference/statements/select/index.md), указанного при создании, и обновляется сразу же при изменении этого результата. Конечный результат запроса и промежуточные данные, из которых формируется результат, хранятся в оперативной памяти, и это обеспечивает высокую скорость обработки для повторяющихся запросов. Живые представления могут отправлять push-уведомления при изменении результата исходного запроса `SELECT`. Для этого используйте запрос [WATCH](../../../sql-reference/statements/watch.md). Изменение живого представления запускается при вставке данных в таблицу, указанную в исходном запросе `SELECT`. Живые представления работают по тому же принципу, что и распределенные таблицы. Но вместо объединения отдельных частей данных с разных серверов, живые представления объединяют уже имеющийся результат с новыми данными. Если в исходном запросе живого представления есть вложенный подзапрос, его результаты не кешируются, в кеше хранится только результат основного запроса. !!! info "Ограничения" - [Табличные функции](../../../sql-reference/table-functions/index.md) в основном запросе не поддерживаются. - Таблицы, не поддерживающие изменение с помощью запроса `INSERT`, такие как [словари](../../../sql-reference/dictionaries/index.md) и [системные таблицы](../../../operations/system-tables/index.md), а также [нормальные представления](#normal) или [материализованные представления](#materialized), не запускают обновление живого представления. - В живых представлениях могут использоваться только такие запросы, которые объединяют результаты по старым и новым данным. Живые представления не работают с запросами, требующими полного пересчета данных или агрегирования с сохранением состояния. - Живое представление не работает для реплицируемых и распределенных таблиц, добавление данных в которые происходит на разных узлах. - Живое представление не обновляется, если в исходном запросе используются несколько таблиц. В случаях, когда живое представление не обновляется автоматически, чтобы обновлять его принудительно с заданной периодичностью, используйте [WITH REFRESH](#live-view-with-refresh). Для отслеживания изменений живого представления используйте запрос [WATCH](../../../sql-reference/statements/watch.md). **Пример:** ```sql CREATE TABLE mt (x Int8) Engine = MergeTree ORDER BY x; CREATE LIVE VIEW lv AS SELECT sum(x) FROM mt; ``` ### Отслеживание изменений {#live-view-monitoring} Отслеживаем изменения живого представления при вставке данных в исходную таблицу. ```sql WATCH lv; ``` ```bash ┌─sum(x)─┬─_version─┐ │ 1 │ 1 │ └────────┴──────────┘ ┌─sum(x)─┬─_version─┐ │ 2 │ 2 │ └────────┴──────────┘ ┌─sum(x)─┬─_version─┐ │ 6 │ 3 │ └────────┴──────────┘ ... ``` ```sql INSERT INTO mt VALUES (1); INSERT INTO mt VALUES (2); INSERT INTO mt VALUES (3); ``` Или используйте ключевое слово [EVENTS](../../../sql-reference/statements/watch.md#events-clause) для получения списка изменений. ```sql WATCH lv EVENTS; ``` ```bash ┌─version─┐ │ 1 │ └─────────┘ ┌─version─┐ │ 2 │ └─────────┘ ┌─version─┐ │ 3 │ └─────────┘ ... ``` Для работы с живыми представлениями, как и с любыми другими, можно использовать запросы [SELECT](../../../sql-reference/statements/select/index.md). Если результат запроса кеширован, он будет возвращен немедленно, без обращения к исходным таблицам представления. ```sql SELECT * FROM [db.]live_view WHERE ... ``` ### Принудительное обновление {#live-view-alter-refresh} Можно принудительно обновить живое представление, используя выражение `ALTER LIVE VIEW [db.]table_name REFRESH`. ### WITH TIMEOUT {#live-view-with-timeout} Живое представление, созданное с параметром `WITH TIMEOUT`, будет автоматически удалено через определенное количество секунд с момента предыдущего запроса [WATCH](../../../sql-reference/statements/watch.md), примененного к данному живому представлению. ```sql CREATE LIVE VIEW [db.]table_name WITH TIMEOUT [value_in_sec] AS SELECT ... ``` Если не было указано значение временного промежутка, используется значение настройки `temporary_live_view_timeout`. **Пример:** ```sql CREATE TABLE mt (x Int8) Engine = MergeTree ORDER BY x; CREATE LIVE VIEW lv WITH TIMEOUT 15 AS SELECT sum(x) FROM mt; ``` ### WITH REFRESH {#live-view-with-refresh} Живое представление, созданное с параметром `WITH REFRESH`, будет автоматически обновляться через указанные промежутки времени, начиная с момента последнего обновления. ```sql CREATE LIVE VIEW [db.]table_name WITH REFRESH [value_in_sec] AS SELECT ... ``` Если значение временного промежутка не задано, используется значение `periodic_live_view_refresh`. **Пример:** ```sql CREATE LIVE VIEW lv WITH REFRESH 5 AS SELECT now(); WATCH lv; ``` ```bash ┌───────────────now()─┬─_version─┐ │ 2021-02-21 08:47:05 │ 1 │ └─────────────────────┴──────────┘ ┌───────────────now()─┬─_version─┐ │ 2021-02-21 08:47:10 │ 2 │ └─────────────────────┴──────────┘ ┌───────────────now()─┬─_version─┐ │ 2021-02-21 08:47:15 │ 3 │ └─────────────────────┴──────────┘ ``` Параметры `WITH TIMEOUT` и `WITH REFRESH` можно сочетать с помощью `AND`. ```sql CREATE LIVE VIEW [db.]table_name WITH TIMEOUT [value_in_sec] AND REFRESH [value_in_sec] AS SELECT ... ``` **Пример:** ```sql CREATE LIVE VIEW lv WITH TIMEOUT 15 AND REFRESH 5 AS SELECT now(); ``` По истечении 15 секунд представление будет автоматически удалено, если нет активного запроса `WATCH`. ```sql WATCH lv ``` ``` Code: 60. DB::Exception: Received from localhost:9000. DB::Exception: Table default.lv doesn't exist.. ``` ### Использование Наиболее вероятные применения живых представлений: - Получение push-уведомлений с изменениями представления, без необходимости отправки запроса для отслеживания изменений. - Кеширование результатов часто используемых запросов для их получения без задержки. - Отслеживание изменений таблицы и запуск последующих запросов `SELECT`. - Отслеживание показателей из системных таблиц с помощью периодических обновлений. ### Параметры {#live-view-settings} Для управления поведением живых представлений можно использовать следующие параметры. - `allow_experimental_live_view` - включить использование живых представлений. По умолчанию установлено `0`. - `live_view_heartbeat_interval` - the heartbeat interval in seconds to indicate live query is alive. Default is `15` seconds. - `live_view_heartbeat_interval` - периодичность индикации активности в секундах, по истечении которого представление «подаст признаки жизни». По умолчанию установлено `15`. - `max_live_view_insert_blocks_before_refresh` - наибольшее число вставок, после которых запрос на формирование представления исполняется снова. По умолчанию количество вставок установлено `64`. - `temporary_live_view_timeout` - interval after which live view with timeout is deleted. Default is `5` seconds. - `temporary_live_view_timeout` - время в секундах, после которого представление удаляется. По умолчанию `5`. - `periodic_live_view_refresh` - interval after which periodically refreshed live view is forced to refresh. Default is `60` seconds. - `periodic_live_view_refresh` - время в секундах, по истечении которого живое представление с установленным автообновлением обновляется. По умолчанию `60`. [Оригинальная статья](https://clickhouse.tech/docs/ru/sql-reference/statements/create/view)