> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-1d264819.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Документация по оператору CREATE VIEW

# CREATE VIEW

export const CloudNotSupportedBadge = () => {
  return <div className="cloudNotSupportedBadge">
            <div className="cloudNotSupportedIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.5" d="M6.33366 12.6666L12.3739 12.6667C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00003 12.3739 8.00003C12.3739 8.00003 12.3337 7.66659 12.0003 7.33325M10.667 5.33322C8.00033 2.33325 4.45395 4.78537 4.14195 6.68203C2.55728 6.7627 1.29395 8.06203 1.29395 9.6667C1.29395 11.3234 2.66699 12.6666 4.00033 12.6666" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.5" d="M2.66699 14L12.0003 4.66663" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

        </div>
            Not supported in ClickHouse Cloud
        </div>;
};

export const DeprecatedBadge = () => {
  return <div className="deprecatedBadge">
            <div className="deprecatedIcon">
            <svg width="14" height="10" viewBox="0 0 14 10" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M13 0H1C0.734784 0 0.48043 0.105357 0.292893 0.292893C0.105357 0.48043 0 0.734784 0 1V2.5C0 2.76522 0.105357 3.01957 0.292893 3.20711C0.48043 3.39464 0.734784 3.5 1 3.5V9C1 9.26522 1.10536 9.51957 1.29289 9.70711C1.48043 9.89464 1.73478 10 2 10H12C12.2652 10 12.5196 9.89464 12.7071 9.70711C12.8946 9.51957 13 9.26522 13 9V3.5C13.2652 3.5 13.5196 3.39464 13.7071 3.20711C13.8946 3.01957 14 2.76522 14 2.5V1C14 0.734784 13.8946 0.48043 13.7071 0.292893C13.5196 0.105357 13.2652 0 13 0ZM12 9H2V3.5H12V9ZM13 2.5H1V1H13V2.5ZM5 5.5C5 5.36739 5.05268 5.24021 5.14645 5.14645C5.24021 5.05268 5.36739 5 5.5 5H8.5C8.63261 5 8.75979 5.05268 8.85355 5.14645C8.94732 5.24021 9 5.36739 9 5.5C9 5.63261 8.94732 5.75979 8.85355 5.85355C8.75979 5.94732 8.63261 6 8.5 6H5.5C5.36739 6 5.24021 5.94732 5.14645 5.85355C5.05268 5.75979 5 5.63261 5 5.5Z" fill="currentColor" />
            </svg>
        </div>
            Deprecated feature
        </div>;
};

export const ExperimentalBadge = () => {
  return <div className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Experimental feature. <u><a href="/docs/beta-and-experimental-features#experimental-features">Learn more.</a></u>
        </div>;
};

Создает новое представление. Представления бывают [обычными](#normal-view), [материализованными](#materialized-view), [обновляемыми материализованными](#refreshable-materialized-view) и [оконными](/ru/reference/statements/create/view#window-view).

<div id="normal-view">
  ## Обычное представление
</div>

Синтаксис:

```sql theme={null}
CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [(alias1 [, alias2 ...])] [ON CLUSTER cluster_name]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

Обычные представления не хранят данные. При каждом обращении они просто читают их из другой таблицы. Иными словами, обычное представление — это всего лишь сохранённый запрос. При чтении из представления этот сохранённый запрос используется как подзапрос в секции [FROM](/ru/reference/statements/select/from).

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

```sql theme={null}
CREATE VIEW view AS SELECT ...
```

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

```sql theme={null}
SELECT a, b, c FROM view
```

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

```sql theme={null}
SELECT a, b, c FROM (SELECT ...)
```

<div id="parameterized-view">
  ## Параметризованное представление
</div>

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

```sql theme={null}
CREATE VIEW view AS SELECT * FROM TABLE WHERE Column1={column1:datatype1} and Column2={column2:datatype2} ...
```

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

```sql theme={null}
SELECT * FROM view(column1=value1, column2=value2 ...)
```

<div id="materialized-view">
  ## Materialized View
</div>

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

`OR REPLACE` и `IF NOT EXISTS` являются взаимоисключающими: их совместное использование вызывает синтаксическую ошибку.

<div id="create-or-replace-materialized-view">
  ### CREATE OR REPLACE MATERIALIZED VIEW
</div>

`CREATE OR REPLACE MATERIALIZED VIEW` атомарно заменяет существующее materialized view и его внутреннюю таблицу хранения (если она есть). Для выполнения этой операции требуется движок базы данных `Atomic` или `Replicated`.

```sql theme={null}
CREATE OR REPLACE MATERIALIZED VIEW [db.]name [ON CLUSTER cluster]
[TO [db.]target_table]
[ENGINE = engine]
[POPULATE]
[REFRESH ...]
AS SELECT ...
```

Ключевые особенности:

* **Без предложения `TO`**: старая внутренняя таблица удаляется и создается новая. Существующие данные во внутренней таблице теряются, если не указан `POPULATE`.
* **С предложением `TO`**: заменяется только определение представления; целевая таблица и ее данные не затрагиваются.
* Совместимо с `REFRESH`, `ON CLUSTER` и любыми параметрами движка. `POPULATE` поддерживается только в базах данных `Atomic` — в базах данных `Replicated` он не допускается (см. примечание о `POPULATE` ниже).
* Требуются привилегии `CREATE VIEW` и `DROP VIEW`.

<Note>
  `CREATE OR REPLACE MATERIALIZED VIEW` поддерживается только для движков баз данных `Atomic` и `Replicated`. Для движка базы данных `Ordinary` это не поддерживается.
</Note>

**Примеры:**

```sql theme={null}
-- Создание materialized view со внутренней таблицей
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, sum(y) AS total FROM src GROUP BY x;

-- Замена новым определением (данные старой внутренней таблицы будут утеряны)
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, count() AS cnt FROM src GROUP BY x;

-- Замена с POPULATE для дозагрузки из существующих исходных данных
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    POPULATE
    AS SELECT x FROM src;

-- Замена MV с внутренней таблицей на MV с TO-таблицей (данные целевой таблицы сохраняются)
CREATE OR REPLACE MATERIALIZED VIEW mv TO target
    AS SELECT x FROM src;
```

<Tip>
  Вот пошаговое руководство по использованию [materialized views](/ru/concepts/features/materialized-views/cascading-materialized-views).
</Tip>

Materialized views хранят данные, преобразованные соответствующим запросом [SELECT](/ru/reference/statements/select).

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

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

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

<Note>
  Materialized views в ClickHouse при вставке в целевую таблицу используют **имена столбцов**, а не их порядок. Если каких-либо имен столбцов нет в результате запроса `SELECT`, ClickHouse использует значение по умолчанию, даже если столбец не имеет тип [Nullable](/ru/reference/data-types/nullable). Поэтому рекомендуется задавать псевдонимы для каждого столбца при использовании materialized views.

  Materialized views в ClickHouse по своей сути больше похожи на триггеры вставки. Если в запросе представления есть агрегация, она применяется только к батчу только что вставленных данных. Любые изменения существующих данных в исходной таблице (например, update, delete, drop partition и т. д.) не изменяют materialized view.

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

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

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

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

<Note>
  Поскольку `POPULATE` работает как `CREATE TABLE ... AS SELECT ...`, у него есть ограничения:

  * Он не поддерживается для базы данных Replicated
  * Он не поддерживается в ClickHouse Cloud

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

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

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

Обратите внимание, что на materialized view влияет настройка [optimize\_on\_insert](/ru/reference/settings/session-settings#optimize_on_insert). Данные объединяются перед вставкой в представление.

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

Чтобы удалить представление, используйте [DROP VIEW](/ru/reference/statements/drop#drop-view). Хотя `DROP TABLE` тоже работает для VIEW.

<div id="sql_security">
  ## Безопасность SQL
</div>

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

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

| Параметр безопасности SQL | Представление                                                                | Materialized View                                                                                                         |
| ------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `DEFINER alice`           | У `alice` должен быть grant `SELECT` на исходную таблицу представления.      | У `alice` должен быть grant `SELECT` на исходную таблицу представления и grant `INSERT` на целевую таблицу представления. |
| `INVOKER`                 | У пользователя должен быть grant `SELECT` на исходную таблицу представления. | `SQL SECURITY INVOKER` нельзя указывать для materialized view.                                                            |
| `NONE`                    | -                                                                            | -                                                                                                                         |

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

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

* `SQL SECURITY`: `INVOKER` для обычных представлений и `DEFINER` для materialized view ([настраивается через settings](/ru/reference/settings/session-settings#default_normal_view_sql_security))
* `DEFINER`: `CURRENT_USER` ([настраивается через settings](/ru/reference/settings/session-settings#default_view_definer))

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

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

```sql theme={null}
ALTER TABLE MODIFY SQL SECURITY { DEFINER | INVOKER | NONE } [DEFINER = { user | CURRENT_USER }]
```

<div id="examples">
  ### Примеры
</div>

```sql theme={null}
CREATE VIEW test_view
DEFINER = alice SQL SECURITY DEFINER
AS SELECT ...
```

```sql theme={null}
CREATE VIEW test_view
SQL SECURITY INVOKER
AS SELECT ...
```

<div id="live-view">
  ## Live View
</div>

Эта возможность объявлена устаревшей и будет удалена в будущем.

Для вашего удобства старая документация находится [здесь](https://pastila.nl/?00f32652/fdf07272a7b54bda7e13b919264e449f.md)

<div id="refreshable-materialized-view">
  ## Refreshable Materialized View
</div>

```sql theme={null}
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
REFRESH EVERY|AFTER interval [OFFSET interval]
[RANDOMIZE FOR interval]
[DEPENDS ON [db.]name [, [db.]name [, ...]]]
[SETTINGS name = value [, name = value [, ...]]]
[APPEND]
[TO[db.]name] [(columns)] [ENGINE = engine]
[EMPTY]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
```

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

```sql theme={null}
number SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
```

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

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

Отличия от обычных non-refreshable materialized views:

* Нет insert trigger. Когда новые данные вставляются в таблицу, указанную в `SELECT`, они *не* передаются автоматически в refreshable materialized view. Вместо этого данные вставляются только во время периодических или ручных обновлений.
* Для запроса `SELECT` нет ограничений. Допускаются table functions (например, `url()`), views, UNION, JOIN.

<Note>
  Настройки в части запроса `REFRESH ... SETTINGS` — это настройки обновления (например, `refresh_retries`), а не обычные настройки (например, `max_threads`). Обычные настройки можно указать с помощью `SETTINGS` в конце запроса.
</Note>

<div id="refresh-schedule">
  ### Расписание обновления
</div>

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

```sql theme={null}
REFRESH EVERY 1 DAY -- каждый день, в полночь (UTC)
REFRESH EVERY 1 MONTH -- в 1-й день каждого месяца, в полночь
REFRESH EVERY 1 MONTH OFFSET 5 DAY 2 HOUR -- в 6-й день каждого месяца, в 2:00
REFRESH EVERY 2 WEEK OFFSET 5 DAY 15 HOUR 10 MINUTE -- каждую вторую субботу, в 15:10
REFRESH EVERY 30 MINUTE -- в 00:00, 00:30, 01:00, 01:30 и т.д.
REFRESH AFTER 30 MINUTE -- через 30 минут после завершения предыдущего обновления, без привязки к времени суток
-- REFRESH AFTER 1 HOUR OFFSET 1 MINUTE -- синтаксическая ошибка: OFFSET не допускается с AFTER
REFRESH EVERY 1 WEEK 2 DAYS -- каждые 9 дней, без привязки к конкретному дню недели или месяца;
                            -- а именно: когда номер дня (начиная с 1969-12-29) кратен 9
REFRESH EVERY 5 MONTHS -- каждые 5 месяцев, в разные месяцы каждого года (так как 12 не кратно 5);
                       -- а именно: когда номер месяца (начиная с 1970-01) кратен 5
```

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

```sql theme={null}
REFRESH EVERY 1 DAY OFFSET 2 HOUR RANDOMIZE FOR 1 HOUR -- каждый день в случайное время между 01:30 и 02:30
```

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

Кроме того, обновление запускается сразу после создания materialized view, если только в запросе `CREATE` не указано `EMPTY`. Если указано `EMPTY`, первое обновление произойдёт по расписанию.

<div id="in-replicated-db">
  ### В базе данных Replicated
</div>

Если refreshable materialized view находится в [базе данных Replicated](/ru/reference/engines/database-engines/replicated), реплики координируют работу между собой так, что в каждый запланированный момент обновление выполняет только одна реплика. Для этого требуется движок таблицы [ReplicatedMergeTree](/ru/reference/engines/table-engines/mergetree-family/replication), чтобы все реплики видели данные, полученные в результате обновления.

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

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

Координация выполняется через Keeper. Путь znode определяется настройкой сервера [default\_replica\_path](/ru/reference/settings/server-settings/settings#default_replica_path).

<div id="refresh-dependencies">
  ### Зависимости обновления
</div>

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

```sql theme={null}
CREATE MATERIALIZED VIEW source REFRESH EVERY 1 DAY AS SELECT * FROM url(...)
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY AS SELECT ... FROM source
```

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

```sql theme={null}
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY DEPENDS ON source AS SELECT ... FROM source
```

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

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

```sql theme={null}
CREATE MATERIALIZED VIEW destination REFRESH AFTER 1 HOUR DEPENDS ON source AS SELECT ... FROM source
```

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

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

* `REFRESH EVERY 1 DAY OFFSET 10 MINUTE` (`destination`) зависит от `REFRESH EVERY 1 DAY` (`source`)<br />
  Если обновление `source` занимает больше 10 минут, `destination` будет его ждать.
* `REFRESH EVERY 1 DAY OFFSET 1 HOUR` зависит от `REFRESH EVERY 1 DAY OFFSET 23 HOUR`<br />
  Аналогично примеру выше, хотя соответствующие обновления происходят в разные календарные дни.
  Обновление `destination` в день `X+1` будет ждать обновления `source` в день `X` (если оно занимает более 2 часов).
* `REFRESH EVERY 2 HOUR` зависит от `REFRESH EVERY 1 HOUR`<br />
  Обновление `2 HOUR` выполняется после обновления `1 HOUR` через каждый второй час, например после полуночного
  обновления, затем после обновления в 2 часа ночи и т. д.
* `REFRESH EVERY 1 MINUTE` зависит от `REFRESH EVERY 2 HOUR`<br />
  `destination` обновляется один раз после каждого обновления `source`, то есть каждые 2 часа. `1 MINUTE` фактически игнорируется.
* `REFRESH AFTER 1 HOUR` зависит от `REFRESH AFTER 1 HOUR`<br />
  В настоящее время это не рекомендуется.

<Note>
  `DEPENDS ON` работает только между refreshable materialized views. Если указать обычную таблицу в списке `DEPENDS ON`, view вообще никогда не будет обновляться (зависимости можно удалить с помощью `ALTER`, см. [Изменение параметров обновления](#changing-refresh-parameters)).
</Note>

<div id="refresh-settings">
  ### Настройки обновления
</div>

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

* `refresh_retries` - Сколько раз повторять попытку, если запрос обновления завершается исключением. Если все повторные попытки завершаются неудачей, обновление пропускается до следующего запланированного времени. 0 означает отсутствие повторных попыток, -1 — бесконечное число повторных попыток. Значение по умолчанию: 2.
* `refresh_retry_initial_backoff_ms` - Задержка перед первой повторной попыткой, если `refresh_retries` не равно нулю. При каждой следующей повторной попытке задержка удваивается, вплоть до `refresh_retry_max_backoff_ms`. Значение по умолчанию: 100 мс.
* `refresh_retry_max_backoff_ms` - Ограничение на экспоненциальный рост задержки между попытками обновления. Значение по умолчанию: 60000 мс (1 минута).
* `all_replicas` - В [Replicated database](/ru/reference/engines/database-engines/replicated) с `APPEND` определяет, будут ли все реплики обновляться независимо или в каждый запланированный момент обновление будет выполнять только одна реплика. Не может быть изменено после создания представления. Значение по умолчанию: `false`.
* `prefer_dependency_replica` - Если у представления есть `DEPENDS ON`, приоритет на выполнение зависимого обновления получает реплика, выполнившая обновление родительского объекта; остальные реплики откладывают свою попытку на `prefer_dependency_replica_delay_ms`. Полезно при использовании `SharedMergeTree`, чтобы избежать ситуаций, когда отставание репликации приводит к отсутствию данных в цепочках зависимых обновлений. Значение по умолчанию: `false`.
* `prefer_dependency_replica_delay_ms` - Как долго неприоритетные реплики ждут перед попыткой выполнить зависимое обновление, когда включен параметр `prefer_dependency_replica`. Значение по умолчанию: 2000 мс.

<div id="changing-refresh-parameters">
  ### Изменение параметров обновления
</div>

Параметры обновления существующей refreshable materialized view изменяются командой [`ALTER TABLE ... MODIFY REFRESH`](/ru/reference/statements/alter/view#alter-table--modify-refresh-statement):

```sql theme={null}
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]
```

Расписание (`EVERY` или `AFTER`) обязательно: этот оператор всегда заменяет *все* параметры обновления — расписание, `RANDOMIZE FOR`, `DEPENDS ON` и настройки обновления — на указанные в нём. Всё, что опущено, сбрасывается к значению по умолчанию (настройки) или удаляется (зависимости, рандомизация).

<Note>
  * Чтобы изменить только настройки обновления (например, `refresh_retries`), заново укажите текущее расписание:

    ```sql theme={null}
    ALTER TABLE rmv MODIFY REFRESH EVERY 1 HOUR SETTINGS refresh_retries = 5;
    ```

  * `ALTER TABLE ... MODIFY SETTING refresh_retries = ...` не поддерживается для materialized view; нужно использовать `MODIFY REFRESH`.

  * Добавлять или удалять `APPEND` не поддерживается.

  * Настройку `all_replicas` нельзя изменить после создания.
</Note>

Примеры:

```sql theme={null}
-- Изменить расписание, удалить существующие настройки и зависимости.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;

-- Изменить расписание и настроить поведение повторных попыток.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
         refresh_retry_initial_backoff_ms = 500,
         refresh_retry_max_backoff_ms = 60000;

-- Сохранить зависимость при изменении периода.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;

-- Удалить зависимость, опустив `DEPENDS ON`.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;
```

<div id="other-operations">
  ### Другие операции
</div>

Статус всех refreshable materialized view доступен в таблице [`system.view_refreshes`](/ru/reference/system-tables/view_refreshes). В частности, в ней содержатся прогресс обновления (если оно выполняется), время последнего и следующего обновления, а также сообщение об исключении, если обновление завершилось ошибкой.

Чтобы вручную остановить, запустить, инициировать или отменить обновления, используйте [`SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW`](/ru/reference/statements/system#managing-refreshable-materialized-views).

Чтобы дождаться завершения обновления, используйте [`SYSTEM WAIT VIEW`](/ru/reference/statements/system#wait-view). Это особенно полезно, если нужно дождаться первого обновления после создания представления.

<Note>
  Интересный факт: запросу обновления разрешено читать из обновляемого представления, при этом он видит версию данных до обновления. Это означает, что вы можете реализовать игру «Жизнь» Конвея: [https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==](https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==)
</Note>

<div id="window-view">
  ## Оконное представление
</div>

<Info>
  Это экспериментальная возможность, которая в будущих выпусках может измениться обратно несовместимым образом. Чтобы включить использование оконных представлений и запроса `WATCH`, включите настройку [allow\_experimental\_window\_view](/ru/reference/settings/session-settings#allow_experimental_window_view). Введите команду `set allow_experimental_window_view = 1`.
</Info>

```sql theme={null}
CREATE WINDOW VIEW [IF NOT EXISTS] [db.]table_name [TO [db.]table_name] [INNER ENGINE engine] [ENGINE engine] [WATERMARK strategy] [ALLOWED_LATENESS interval_function] [POPULATE]
AS SELECT ...
GROUP BY time_window_function
[COMMENT 'comment']
```

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

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

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

<div id="time-window-functions">
  ### Функции временных окон
</div>

[Функции временных окон](/ru/reference/functions/regular-functions/time-window-functions) используются для получения нижней и верхней границ окна для записей. Оконное представление необходимо использовать вместе с функцией временного окна.

<div id="time-attributes">
  ### АТРИБУТЫ ВРЕМЕНИ
</div>

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

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

```sql theme={null}
CREATE WINDOW VIEW wv AS SELECT count(number), tumbleStart(w_id) as w_start from date GROUP BY tumble(now(), INTERVAL '5' SECOND) as w_id
```

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

Оконное представление поддерживает три стратегии водяной метки:

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

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

```sql theme={null}
CREATE WINDOW VIEW wv WATERMARK=STRICTLY_ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=INTERVAL '3' SECOND AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
```

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

```sql theme={null}
CREATE WINDOW VIEW test.wv TO test.dst WATERMARK=ASCENDING ALLOWED_LATENESS=INTERVAL '2' SECOND AS SELECT count(a) AS count, tumbleEnd(wid) AS w_end FROM test.mt GROUP BY tumble(timestamp, INTERVAL '5' SECOND) AS wid;
```

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

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

<div id="monitoring-new-windows">
  ### Мониторинг новых окон
</div>

Оконное представление поддерживает запрос [WATCH](/ru/reference/statements/watch) для мониторинга изменений, либо можно использовать синтаксис `TO` для вывода результатов в таблицу.

```sql theme={null}
WATCH [db.]window_view
[EVENTS]
[LIMIT n]
[FORMAT format]
```

Можно указать `LIMIT`, чтобы задать количество обновлений, которые нужно получить до завершения запроса. Предложение `EVENTS` позволяет использовать сокращённую форму запроса `WATCH`: вместо результата запроса вы получите только последнюю водяную метку запроса.

<div id="settings-1">
  ### Настройки
</div>

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

<div id="example">
  ### Пример
</div>

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

```sql theme={null}
CREATE TABLE data ( `id` UInt64, `timestamp` DateTime) ENGINE = Memory;
```

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

```sql theme={null}
CREATE WINDOW VIEW wv as select count(id), tumbleStart(w_id) as window_start from data group by tumble(timestamp, INTERVAL '10' SECOND) as w_id
```

Затем с помощью запроса `WATCH` получаем результаты.

```sql theme={null}
WATCH wv
```

При вставке логов в таблицу `data`,

```sql theme={null}
INSERT INTO data VALUES(1,now())
```

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

```text theme={null}
┌─count(id)─┬────────window_start─┐
│         1 │ 2020-01-14 16:56:40 │
└───────────┴─────────────────────┘
```

Либо можно направить вывод в другую таблицу, используя синтаксис `TO`.

```sql theme={null}
CREATE WINDOW VIEW wv TO dst AS SELECT count(id), tumbleStart(w_id) as window_start FROM data GROUP BY tumble(timestamp, INTERVAL '10' SECOND) as w_id
```

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

<div id="window-view-usage">
  ### Использование оконного представления
</div>

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

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

<div id="related-content">
  ## Связанные материалы
</div>

* Блог: [Работа с временными рядами в ClickHouse](https://clickhouse.com/blog/working-with-time-series-data-and-functions-ClickHouse)
* Блог: [Создание решения для обсервабилити на ClickHouse — часть 2 — трейсы](https://clickhouse.com/blog/storing-traces-and-spans-open-telemetry-in-clickhouse)

<div id="temporary-views">
  ## Временные представления
</div>

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 временного представления.

<div id="temporary-views-syntax">
  ### Синтаксис
</div>

```sql theme={null}
CREATE TEMPORARY VIEW [IF NOT EXISTS] view_name AS <select_query>
```

`OR REPLACE` **не** поддерживается для временных представлений (по аналогии с временными таблицами). Если вам нужно «заменить» временное представление, удалите его и создайте заново.

<div id="examples">
  ### Примеры
</div>

Создайте временную исходную таблицу и временное представление на её основе:

```sql theme={null}
CREATE TEMPORARY TABLE t_src (id UInt32, val String);
INSERT INTO t_src VALUES (1, 'a'), (2, 'b');

CREATE TEMPORARY VIEW tview AS
SELECT id, upper(val) AS u
FROM t_src
WHERE id <= 2;

SELECT * FROM tview ORDER BY id;
```

Показать DDL:

```sql theme={null}
SHOW CREATE TEMPORARY VIEW tview;
```

Удалить её:

```sql theme={null}
DROP TEMPORARY VIEW IF EXISTS tview;  -- временные представления удаляются с использованием синтаксиса TEMPORARY TABLE
```

<div id="temporary-views-limitations">
  ### Недопустимые варианты / ограничения
</div>

* `CREATE OR REPLACE TEMPORARY VIEW ...` → **не допускается** (используйте `DROP` + `CREATE`).
* `CREATE TEMPORARY MATERIALIZED VIEW ...` / `WINDOW VIEW` → **не допускается**.
* `CREATE TEMPORARY VIEW db.view AS ...` → **не допускается** (без указания базы данных).
* `CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...` → **не допускается** (временные объекты локальны для сеанса).
* `POPULATE`, `REFRESH`, `TO [db.table]`, внутренние движки и все специфичные для MV секции → **не применимы** к временным представлениям.

<div id="temporary-views-distributed-notes">
  ### Примечания о распределённых запросах
</div>

Временное **представление** — это лишь определение; передавать здесь нечего. Если ваше временное представление ссылается на временные **таблицы** (например, `Memory`), их данные могут передаваться на удалённые серверы при выполнении распределённого запроса — так же, как и в случае временных таблиц.

<div id="temporary-views-distributed-example">
  #### Пример
</div>

```sql theme={null}
-- Таблица в памяти в рамках сеанса
CREATE TEMPORARY TABLE temp_ids (id UInt64) ENGINE = Memory;

INSERT INTO temp_ids VALUES (1), (5), (42);

-- Представление в рамках сеанса над временной таблицей (исключительно логическое)
CREATE TEMPORARY VIEW v_ids AS
SELECT id FROM temp_ids;

-- Замените 'test' именем вашего кластера.
-- GLOBAL JOIN заставляет ClickHouse *отправлять* небольшую сторону JOIN (temp_ids через v_ids)
-- на каждый удалённый сервер, выполняющий левую часть запроса.
SELECT count()
FROM cluster('test', system.numbers) AS n
GLOBAL ANY INNER JOIN v_ids USING (id)
WHERE n.number < 100;

```
