ClickHouse/docs/ru/engines/table-engines/mergetree-family/mergetree.md

877 lines
78 KiB
Markdown
Raw Normal View History

---
toc_priority: 30
toc_title: MergeTree
---
# MergeTree {#table_engines-mergetree}
2019-08-23 10:55:34 +00:00
Движок `MergeTree`, а также другие движки этого семейства (`*MergeTree`) — это наиболее функциональные движки таблиц ClickHouse.
Основная идея, заложенная в основу движков семейства `MergeTree` следующая. Когда у вас есть огромное количество данных, которые должны быть вставлены в таблицу, вы должны быстро записать их по частям, а затем объединить части по некоторым правилам в фоновом режиме. Этот метод намного эффективнее, чем постоянная перезапись данных в хранилище при вставке.
2018-08-21 07:54:37 +00:00
Основные возможности:
- **Хранит данные, отсортированные по первичному ключу.** Это позволяет создавать разреженный индекс небольшого объёма, который позволяет быстрее находить данные.
2018-08-21 07:54:37 +00:00
- **Позволяет оперировать партициями, если задан [ключ партиционирования](custom-partitioning-key.md).** ClickHouse поддерживает отдельные операции с партициями, которые работают эффективнее, чем общие операции с этим же результатом над этими же данными. Также, ClickHouse автоматически отсекает данные по партициям там, где ключ партиционирования указан в запросе. Это также увеличивает эффективность выполнения запросов.
2018-08-21 07:54:37 +00:00
- **Поддерживает репликацию данных.** Для этого используется семейство таблиц `ReplicatedMergeTree`. Подробнее читайте в разделе [Репликация данных](replication.md).
2018-08-21 07:54:37 +00:00
- **Поддерживает сэмплирование данных.** При необходимости можно задать способ сэмплирования данных в таблице.
2018-08-21 07:54:37 +00:00
!!! info "Info"
DOCS-624: Fixing links to nowhere (#10675) * enbaskakova-DOCSUP-652 (#101) * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: BayoNet <da-daos@yandex.ru> * Revert "enbaskakova-DOCSUP-652 (#101)" (#107) This reverts commit 639fee7610f28e421d14e535b7def3f466e7efca. * CLICKHOUSEDOCS-624: Fixed links. Was 60, became 13. * CLICKHOUSEDOCS-624: Finished fix links in Enlish version. * CLICKHOUSEDOCS-624: Fixed RU links Co-authored-by: elenaspb2019 <47083263+elenaspb2019@users.noreply.github.com> Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: Sergei Shtykov <bayonet@yandex-team.ru>
2020-05-06 06:13:29 +00:00
Движок [Merge](../special/merge.md#merge) не относится к семейству `*MergeTree`.
## Создание таблицы {#table_engine-mergetree-creating-a-table}
``` sql
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
...
2019-01-21 18:35:29 +00:00
INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
ORDER BY expr
[PARTITION BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
2021-06-01 14:23:46 +00:00
[TTL expr
2021-01-23 18:16:59 +00:00
[DELETE|TO DISK 'xxx'|TO VOLUME 'xxx' [, ...] ]
2021-06-01 14:23:46 +00:00
[WHERE conditions]
[GROUP BY key_expr [SET v1 = aggr_func(v1) [, v2 = aggr_func(v2) ...]] ] ]
[SETTINGS name=value, ...]
```
2018-08-21 07:54:37 +00:00
Описание параметров смотрите в [описании запроса CREATE](../../../engines/table-engines/mergetree-family/mergetree.md).
2020-01-28 15:27:44 +00:00
### Секции запроса {#mergetree-query-clauses}
2018-08-21 07:54:37 +00:00
- `ENGINE` — имя и параметры движка. `ENGINE = MergeTree()`. `MergeTree` не имеет параметров.
2018-08-21 07:54:37 +00:00
- `ORDER BY` — ключ сортировки.
2021-06-01 14:23:46 +00:00
Кортеж столбцов или произвольных выражений. Пример: `ORDER BY (CounterID, EventDate)`.
ClickHouse использует ключ сортировки в качестве первичного ключа, если первичный ключ не задан в секции `PRIMARY KEY`.
2021-06-01 14:23:46 +00:00
Чтобы отключить сортировку, используйте синтаксис `ORDER BY tuple()`. Смотрите [выбор первичного ключа](#primary-keys-and-indexes-in-queries).
- `PARTITION BY` — [ключ партиционирования](custom-partitioning-key.md). Необязательный параметр.
Для партиционирования по месяцам используйте выражение `toYYYYMM(date_column)`, где `date_column` — столбец с датой типа [Date](../../../engines/table-engines/mergetree-family/mergetree.md). В этом случае имена партиций имеют формат `"YYYYMM"`.
2018-08-22 06:32:16 +00:00
2021-03-06 11:25:37 +00:00
- `PRIMARY KEY` — первичный ключ, если он [отличается от ключа сортировки](#choosing-a-primary-key-that-differs-from-the-sorting-key). Необязательный параметр.
2021-06-01 14:23:46 +00:00
По умолчанию первичный ключ совпадает с ключом сортировки (который задаётся секцией `ORDER BY`.) Поэтому в большинстве случаев секцию `PRIMARY KEY` отдельно указывать не нужно.
- `SAMPLE BY` — выражение для сэмплирования. Необязательный параметр.
2021-06-01 14:23:46 +00:00
2021-08-05 19:55:19 +00:00
Если используется выражение для сэмплирования, то первичный ключ должен содержать его. Результат выражения для сэмплирования должен быть беззнаковым целым числом. Пример: `SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))`.
- `TTL` — список правил, определяющих длительности хранения строк, а также задающих правила перемещения частей на определённые тома или диски. Необязательный параметр.
2021-06-01 14:23:46 +00:00
Выражение должно возвращать столбец `Date` или `DateTime`. Пример: `TTL date + INTERVAL 1 DAY`.
2021-02-01 23:44:40 +00:00
Тип правила `DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'|GROUP BY` указывает действие, которое будет выполнено с частью: удаление строк (прореживание), перемещение (при выполнении условия для всех строк части) на определённый диск (`TO DISK 'xxx'`) или том (`TO VOLUME 'xxx'`), или агрегирование данных в устаревших строках. Поведение по умолчанию соответствует удалению строк (`DELETE`). В списке правил может быть указано только одно выражение с поведением `DELETE`.
2021-06-01 14:23:46 +00:00
Дополнительные сведения смотрите в разделе [TTL для столбцов и таблиц](#table_engine-mergetree-ttl)
- `SETTINGS` — дополнительные параметры, регулирующие поведение `MergeTree` (необязательные):
2018-08-21 07:54:37 +00:00
- `index_granularity` — максимальное количество строк данных между засечками индекса. По умолчанию — 8192. Смотрите [Хранение данных](#mergetree-data-storage).
- `index_granularity_bytes` — максимальный размер гранул данных в байтах. По умолчанию — 10Mb. Чтобы ограничить размер гранул только количеством строк, установите значение 0 (не рекомендовано). Смотрите [Хранение данных](#mergetree-data-storage).
- `min_index_granularity_bytes` — минимально допустимый размер гранул данных в байтах. Значение по умолчанию — 1024b. Для обеспечения защиты от случайного создания таблиц с очень низким значением `index_granularity_bytes`. Смотрите [Хранение данных](#mergetree-data-storage).
- `enable_mixed_granularity_parts` — включает или выключает переход к ограничению размера гранул с помощью настройки `index_granularity_bytes`. Настройка `index_granularity_bytes` улучшает производительность ClickHouse при выборке данных из таблиц с большими (десятки и сотни мегабайтов) строками. Если у вас есть таблицы с большими строками, можно включить эту настройку, чтобы повысить эффективность запросов `SELECT`.
- `use_minimalistic_part_header_in_zookeeper` — Способ хранения заголовков кусков данных в ZooKeeper. Если `use_minimalistic_part_header_in_zookeeper = 1`, то ZooKeeper хранит меньше данных. Подробнее читайте в [описании настройки](../../../operations/server-configuration-parameters/settings.md#server-settings-use_minimalistic_part_header_in_zookeeper) в разделе "Конфигурационные параметры сервера".
- `min_merge_bytes_to_use_direct_io` — минимальный объём данных при слиянии, необходимый для прямого (небуферизованного) чтения/записи (direct I/O) на диск. При слиянии частей данных ClickHouse вычисляет общий объём хранения всех данных, подлежащих слиянию. Если общий объём хранения всех данных для чтения превышает `min_bytes_to_use_direct_io` байт, тогда ClickHouse использует флаг `O_DIRECT` при чтении данных с диска. Если `min_merge_bytes_to_use_direct_io = 0`, тогда прямой ввод-вывод отключен. Значение по умолчанию: `10 * 1024 * 1024 * 1024` байтов.
- <a name="mergetree_setting-merge_with_ttl_timeout"></a>`merge_with_ttl_timeout` — минимальное время в секундах перед повторным слиянием с TTL. По умолчанию — 86400 (1 день).
- `write_final_mark` — включает или отключает запись последней засечки индекса в конце куска данных, указывающей за последний байт. По умолчанию — 1. Не отключайте её.
- `merge_max_block_size` — максимальное количество строк в блоке для операций слияния. Значение по умолчанию: 8192.
- `storage_policy` — политика хранения данных. Смотрите [Хранение данных таблицы на нескольких блочных устройствах](#table_engine-mergetree-multiple-volumes).
- `min_bytes_for_wide_part`, `min_rows_for_wide_part` — минимальное количество байт/строк в куске данных для хранения в формате `Wide`. Можно задать одну или обе настройки или не задавать ни одной. Подробнее см. в разделе [Хранение данных](#mergetree-data-storage).
- `max_parts_in_total` — максимальное количество кусков во всех партициях.
- `max_compress_block_size` — максимальный размер блоков несжатых данных перед сжатием для записи в таблицу. Вы также можете задать этот параметр в глобальных настройках (смотрите [max_compress_block_size](../../../operations/settings/settings.md#max-compress-block-size)). Настройка, которая задается при создании таблицы, имеет более высокий приоритет, чем глобальная.
- `min_compress_block_size` — минимальный размер блоков несжатых данных, необходимых для сжатия при записи следующей засечки. Вы также можете задать этот параметр в глобальных настройках (смотрите [min_compress_block_size](../../../operations/settings/settings.md#min-compress-block-size)). Настройка, которая задается при создании таблицы, имеет более высокий приоритет, чем глобальная.
2021-02-05 09:46:59 +00:00
- `max_partitions_to_read` — Ограничивает максимальное число партиций для чтения в одном запросе. Также возможно указать настройку [max_partitions_to_read](../../../operations/settings/merge-tree-settings.md#max-partitions-to-read) в глобальных настройках.
**Пример задания секций**
2018-08-21 07:54:37 +00:00
``` sql
2018-08-21 07:54:37 +00:00
ENGINE MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192
```
В примере мы устанавливаем партиционирование по месяцам.
Также мы задаем выражение для сэмплирования в виде хэша по идентификатору посетителя. Это позволяет псевдослучайным образом перемешать данные в таблице для каждого `CounterID` и `EventDate`. Если при выборке данных задать секцию [SAMPLE](../../../engines/table-engines/mergetree-family/mergetree.md#select-sample-clause), то ClickHouse вернёт равномерно-псевдослучайную выборку данных для подмножества посетителей.
2018-08-21 07:54:37 +00:00
`index_granularity` можно было не указывать, поскольку 8192 — это значение по умолчанию.
<details markdown="1">
<summary>Устаревший способ создания таблицы</summary>
2018-08-21 07:54:37 +00:00
!!! attention "Attention"
Не используйте этот способ в новых проектах и по возможности переведите старые проекты на способ, описанный выше.
``` sql
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE [=] MergeTree(date-column [, sampling_expression], (primary, key), index_granularity)
2018-08-21 07:54:37 +00:00
```
**Параметры MergeTree()**
- `date-column` — имя столбца с типом [Date](../../../engines/table-engines/mergetree-family/mergetree.md). На основе этого столбца ClickHouse автоматически создаёт партиции по месяцам. Имена партиций имеют формат `"YYYYMM"`.
- `sampling_expression` — выражение для сэмплирования.
- `(primary, key)` — первичный ключ. Тип — [Tuple()](../../../engines/table-engines/mergetree-family/mergetree.md)
- `index_granularity` — гранулярность индекса. Число строк данных между «засечками» индекса. Для большинства задач подходит значение 8192.
2018-08-21 07:54:37 +00:00
**Пример**
``` sql
MergeTree(EventDate, intHash32(UserID), (CounterID, EventDate, intHash32(UserID)), 8192)
```
2018-08-21 07:54:37 +00:00
Движок `MergeTree` сконфигурирован таким же образом, как и в примере выше для основного способа конфигурирования движка.
</details>
2018-08-21 07:54:37 +00:00
## Хранение данных {#mergetree-data-storage}
2018-08-21 07:54:37 +00:00
2018-08-22 06:44:04 +00:00
Таблица состоит из *кусков* данных (data parts), отсортированных по первичному ключу.
2018-08-21 07:54:37 +00:00
2018-08-22 06:44:04 +00:00
При вставке в таблицу создаются отдельные куски данных, каждый из которых лексикографически отсортирован по первичному ключу. Например, если первичный ключ — `(CounterID, Date)`, то данные в куске будут лежать в порядке `CounterID`, а для каждого `CounterID` в порядке `Date`.
2018-08-21 07:54:37 +00:00
Данные, относящиеся к разным партициям, разбиваются на разные куски. В фоновом режиме ClickHouse выполняет слияния (merge) кусков данных для более эффективного хранения. Куски, относящиеся к разным партициям не объединяются. Механизм слияния не гарантирует, что все строки с одинаковым первичным ключом окажутся в одном куске.
2018-08-21 07:54:37 +00:00
2021-06-01 14:23:46 +00:00
Куски данных могут храниться в формате `Wide` или `Compact`. В формате `Wide` каждый столбец хранится в отдельном файле, а в формате `Compact` все столбцы хранятся в одном файле. Формат `Compact` может быть полезен для повышения производительности при частом добавлении небольших объемов данных.
Формат хранения определяется настройками движка `min_bytes_for_wide_part` и `min_rows_for_wide_part`. Если число байт или строк в куске данных меньше значения, указанного в соответствующей настройке, тогда этот кусок данных хранится в формате `Compact`. В противном случае кусок данных хранится в формате `Wide`. Если ни одна из настроек не задана, куски данных хранятся в формате `Wide`.
Каждый кусок данных логически делится на гранулы. Гранула — это минимальный неделимый набор данных, который ClickHouse считывает при выборке данных. ClickHouse не разбивает строки и значения и гранула всегда содержит целое число строк. Первая строка гранулы помечается значением первичного ключа для этой строки (засечка). Для каждого куска данных ClickHouse создаёт файл с засечками (индексный файл). Для каждого столбца, независимо от того, входит он в первичный ключ или нет, ClickHouse также сохраняет эти же засечки. Засечки используются для поиска данных напрямую в файлах столбцов.
Размер гранул оганичен настройками движка `index_granularity` и `index_granularity_bytes`. Количество строк в грануле лежит в диапазоне `[1, index_granularity]`, в зависимости от размера строк. Размер гранулы может превышать `index_granularity_bytes` в том случае, когда размер единственной строки в грануле превышает значение настройки. В этом случае, размер гранулы равен размеру строки.
2018-08-21 07:54:37 +00:00
## Первичные ключи и индексы в запросах {#primary-keys-and-indexes-in-queries}
2018-08-21 07:54:37 +00:00
Рассмотрим первичный ключ — `(CounterID, Date)`. В этом случае сортировку и индекс можно проиллюстрировать следующим образом:
2018-08-21 07:54:37 +00:00
``` text
2018-08-21 07:54:37 +00:00
Whole data: [-------------------------------------------------------------------------]
CounterID: [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiikllllllll]
Date: [1111111222222233331233211111222222333211111112122222223111112223311122333]
Marks: | | | | | | | | | | |
a,1 a,2 a,3 b,3 e,2 e,3 g,1 h,2 i,1 i,3 l,3
Marks numbers: 0 1 2 3 4 5 6 7 8 9 10
```
Если в запросе к данным указать:
- `CounterID IN ('a', 'h')`, то сервер читает данные в диапазонах засечек `[0, 3)` и `[6, 8)`.
- `CounterID IN ('a', 'h') AND Date = 3`, то сервер читает данные в диапазонах засечек `[1, 3)` и `[7, 8)`.
- `Date = 3`, то сервер читает данные в диапазоне засечек `[1, 10]`.
2018-08-21 07:54:37 +00:00
Примеры выше показывают, что использование индекса всегда эффективнее, чем full scan.
Разреженный индекс допускает чтение лишних строк. При чтении одного диапазона первичного ключа, может быть прочитано до `index_granularity * 2` лишних строк в каждом блоке данных.
2020-03-16 15:02:03 +00:00
Разреженный индекс почти всегда помещаеся в оперативную память и позволяет работать с очень большим количеством строк в таблицах.
2018-08-21 07:54:37 +00:00
ClickHouse не требует уникального первичного ключа. Можно вставить много строк с одинаковым первичным ключом.
Ключ в `PRIMARY KEY` и `ORDER BY` может иметь тип `Nullable`. За поддержку этой возможности отвечает настройка [allow_nullable_key](../../../operations/settings/settings.md#allow-nullable-key).
При сортировке с использованием выражения `ORDER BY` для значений `NULL` всегда работает принцип [NULLS_LAST](../../../sql-reference/statements/select/order-by.md#sorting-of-special-values).
2021-03-06 11:13:14 +00:00
### Выбор первичного ключа {#selecting-the-primary-key}
2018-08-21 07:54:37 +00:00
Количество столбцов в первичном ключе не ограничено явным образом. В зависимости от структуры данных в первичный ключ можно включать больше или меньше столбцов. Это может:
- Увеличить эффективность индекса.
2020-12-01 03:18:16 +00:00
Пусть первичный ключ — `(a, b)`, тогда добавление ещё одного столбца `c` повысит эффективность, если выполнены условия:
2020-12-01 03:18:16 +00:00
- Есть запросы с условием на столбец `c`.
- Часто встречаются достаточно длинные (в несколько раз больше `index_granularity`) диапазоны данных с одинаковыми значениями `(a, b)`. Иначе говоря, когда добавление ещё одного столбца позволит пропускать достаточно длинные диапазоны данных.
- Улучшить сжатие данных.
2018-08-21 07:54:37 +00:00
2020-12-01 03:18:16 +00:00
ClickHouse сортирует данные по первичному ключу, поэтому чем выше однородность, тем лучше сжатие.
2018-08-21 07:54:37 +00:00
- Обеспечить дополнительную логику при слиянии кусков данных в движках [CollapsingMergeTree](collapsingmergetree.md#table_engine-collapsingmergetree) и [SummingMergeTree](summingmergetree.md).
2018-08-21 07:54:37 +00:00
2020-12-01 03:18:16 +00:00
В этом случае имеет смысл указать отдельный *ключ сортировки*, отличающийся от первичного ключа.
2018-08-21 07:54:37 +00:00
Длинный первичный ключ будет негативно влиять на производительность вставки и потребление памяти, однако на производительность ClickHouse при запросах `SELECT` лишние столбцы в первичном ключе не влияют.
2020-10-13 17:23:29 +00:00
Вы можете создать таблицу без первичного ключа, используя синтаксис `ORDER BY tuple()`. В этом случае ClickHouse хранит данные в порядке вставки. Если вы хотите сохранить порядок данных при вставке данных с помощью запросов `INSERT ... SELECT`, установите [max_insert_threads = 1](../../../operations/settings/settings.md#settings-max-insert-threads).
2021-06-01 14:23:46 +00:00
Чтобы выбрать данные в первоначальном порядке, используйте
[однопоточные](../../../operations/settings/settings.md#settings-max_threads) запросы `SELECT.
2021-03-06 11:13:14 +00:00
### Первичный ключ, отличный от ключа сортировки {#choosing-a-primary-key-that-differs-from-the-sorting-key}
Существует возможность задать первичный ключ (выражение, значения которого будут записаны в индексный файл для
2019-03-21 10:53:46 +00:00
каждой засечки), отличный от ключа сортировки (выражение, по которому будут упорядочены строки в кусках
данных). Кортеж выражения первичного ключа при этом должен быть префиксом кортежа выражения ключа
сортировки.
Данная возможность особенно полезна при использовании движков [SummingMergeTree](summingmergetree.md)
и [AggregatingMergeTree](aggregatingmergetree.md). В типичном сценарии использования этих движков таблица
содержит столбцы двух типов: *измерения* (dimensions) и *меры* (measures). Типичные запросы агрегируют
значения столбцов-мер с произвольной группировкой и фильтрацией по измерениям. Так как `SummingMergeTree`
и `AggregatingMergeTree` производят фоновую агрегацию строк с одинаковым значением ключа сортировки, приходится
добавлять в него все столбцы-измерения. В результате выражение ключа содержит большой список столбцов,
который приходится постоянно расширять при добавлении новых измерений.
В этом сценарии имеет смысл оставить в первичном ключе всего несколько столбцов, которые обеспечат эффективную фильтрацию по индексу, а остальные столбцы-измерения добавить в выражение ключа сортировки.
[ALTER ключа сортировки](../../../engines/table-engines/mergetree-family/mergetree.md) — лёгкая операция, так как при одновременном добавлении нового столбца в таблицу и ключ сортировки не нужно изменять данные кусков (они остаются упорядоченными и по новому выражению ключа).
2021-03-06 11:13:14 +00:00
### Использование индексов и партиций в запросах {#use-of-indexes-and-partitions-in-queries}
2018-08-21 07:54:37 +00:00
Для запросов `SELECT` ClickHouse анализирует возможность использования индекса. Индекс может использоваться, если в секции `WHERE/PREWHERE`, в качестве одного из элементов конъюнкции, или целиком, есть выражение, представляющее операции сравнения на равенства, неравенства, а также `IN` или `LIKE` с фиксированным префиксом, над столбцами или выражениями, входящими в первичный ключ или ключ партиционирования, либо над некоторыми частично монотонными функциями от этих столбцов, а также логические связки над такими выражениями.
2018-03-15 11:48:19 +00:00
Таким образом, обеспечивается возможность быстро выполнять запросы по одному или многим диапазонам первичного ключа. Например, в указанном примере будут быстро работать запросы для конкретного счётчика; для конкретного счётчика и диапазона дат; для конкретного счётчика и даты, для нескольких счётчиков и диапазона дат и т. п.
2018-08-21 07:54:37 +00:00
Рассмотрим движок сконфигурированный следующим образом:
``` sql
2018-08-21 07:54:37 +00:00
ENGINE MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate) SETTINGS index_granularity=8192
```
В этом случае в запросах:
``` sql
SELECT count() FROM table WHERE EventDate = toDate(now()) AND CounterID = 34
SELECT count() FROM table WHERE EventDate = toDate(now()) AND (CounterID = 34 OR CounterID = 42)
SELECT count() FROM table WHERE ((EventDate >= toDate('2014-01-01') AND EventDate <= toDate('2014-01-31')) OR EventDate = toDate('2014-05-01')) AND CounterID IN (101500, 731962, 160656) AND (CounterID = 101500 OR EventDate != toDate('2014-05-01'))
```
2018-08-21 07:54:37 +00:00
ClickHouse будет использовать индекс по первичному ключу для отсечения не подходящих данных, а также ключ партиционирования по месяцам для отсечения партиций, которые находятся в не подходящих диапазонах дат.
Запросы выше показывают, что индекс используется даже для сложных выражений. Чтение из таблицы организовано так, что использование индекса не может быть медленнее, чем full scan.
2018-08-21 07:54:37 +00:00
В примере ниже индекс не может использоваться.
``` sql
SELECT count() FROM table WHERE CounterID = 34 OR URL LIKE '%upyachka%'
```
2020-10-13 17:23:29 +00:00
Чтобы проверить, сможет ли ClickHouse использовать индекс при выполнении запроса, используйте настройки [force_index_by_date](../../../operations/settings/settings.md#settings-force_index_by_date) и [force_primary_key](../../../operations/settings/settings.md#settings-force_primary_key).
2018-08-21 07:54:37 +00:00
Ключ партиционирования по месяцам обеспечивает чтение только тех блоков данных, которые содержат даты из нужного диапазона. При этом блок данных может содержать данные за многие даты (до целого месяца). В пределах одного блока данные упорядочены по первичному ключу, который может не содержать дату в качестве первого столбца. В связи с этим, при использовании запроса с указанием условия только на дату, но не на префикс первичного ключа, будет читаться данных больше, чем за одну дату.
2021-03-06 11:13:14 +00:00
### Использование индекса для частично-монотонных первичных ключей {#use-of-index-for-partially-monotonic-primary-keys}
Рассмотрим, например, дни месяца. Они образуют последовательность [монотонную](https://ru.wikipedia.org/wiki/Монотонная_последовательность) в течение одного месяца, но не монотонную на более длительных периодах. Это частично-монотонная последовательность. Если пользователь создаёт таблицу с частично-монотонным первичным ключом, ClickHouse как обычно создаёт разреженный индекс. Когда пользователь выбирает данные из такого рода таблиц, ClickHouse анализирует условия запроса. Если пользователь хочет получить данные между двумя метками индекса, и обе эти метки находятся внутри одного месяца, ClickHouse может использовать индекс в данном конкретном случае, поскольку он может рассчитать расстояние между параметрами запроса и индексными метками.
ClickHouse не может использовать индекс, если значения первичного ключа в диапазоне параметров запроса не представляют собой монотонную последовательность. В этом случае ClickHouse использует метод полного сканирования.
ClickHouse использует эту логику не только для последовательностей дней месяца, но и для любого частично-монотонного первичного ключа.
2020-09-16 06:13:28 +00:00
### Индексы пропуска данных {#table_engine-mergetree-data_skipping-indexes}
Объявление индексов при определении столбцов в запросе `CREATE`.
``` sql
INDEX index_name expr TYPE type(...) GRANULARITY granularity_value
```
2019-02-12 18:02:45 +00:00
2019-01-21 18:35:29 +00:00
Для таблиц семейства `*MergeTree` можно задать дополнительные индексы в секции столбцов.
2020-02-02 21:46:31 +00:00
Индексы агрегируют для заданного выражения некоторые данные, а потом при `SELECT` запросе используют для пропуска блоков данных (пропускаемый блок состоит из гранул данных в количестве равном гранулярности данного индекса), на которых секция `WHERE` не может быть выполнена, тем самым уменьшая объём данных читаемых с диска.
2019-01-21 18:35:29 +00:00
**Пример**
``` sql
2019-01-21 18:35:29 +00:00
CREATE TABLE table_name
(
u64 UInt64,
i32 Int32,
s String,
...
INDEX a (u64 * i32, s) TYPE minmax GRANULARITY 3,
INDEX b (u64 * length(s)) TYPE set(1000) GRANULARITY 4
2019-01-21 18:35:29 +00:00
) ENGINE = MergeTree()
...
```
2019-01-22 18:22:16 +00:00
Эти индексы смогут использоваться для оптимизации следующих запросов
``` sql
2019-01-21 18:35:29 +00:00
SELECT count() FROM table WHERE s < 'z'
SELECT count() FROM table WHERE u64 * i32 == 10 AND u64 * length(s) >= 1234
```
2021-03-06 11:13:14 +00:00
#### Доступные индексы {#available-types-of-indices}
2019-01-21 18:35:29 +00:00
- `minmax` — Хранит минимум и максимум выражения (если выражение - `tuple`, то для каждого элемента `tuple`), используя их для пропуска блоков аналогично первичному ключу.
- `set(max_rows)` — Хранит уникальные значения выражения на блоке в количестве не более `max_rows` (если `max_rows = 0`, то ограничений нет), используя их для пропуска блоков, оценивая выполнимость `WHERE` выражения на хранимых данных.
- `bloom_filter([false_positive])` — [фильтр Блума](https://en.wikipedia.org/wiki/Bloom_filter) для указанных стоблцов.
2020-12-01 03:18:16 +00:00
Необязательный параметр `false_positive` — это вероятность получения ложноположительного срабатывания. Возможные значения: (0, 1). Значение по умолчанию: 0.025.
2020-12-01 03:18:16 +00:00
Поддержанные типы данных: `Int*`, `UInt*`, `Float*`, `Enum`, `Date`, `DateTime`, `String`, `FixedString`.
2021-06-01 14:23:46 +00:00
2020-12-01 17:51:08 +00:00
Фильтром могут пользоваться функции: [equals](../../../engines/table-engines/mergetree-family/mergetree.md), [notEquals](../../../engines/table-engines/mergetree-family/mergetree.md), [in](../../../engines/table-engines/mergetree-family/mergetree.md), [notIn](../../../engines/table-engines/mergetree-family/mergetree.md).
2019-01-21 18:35:29 +00:00
**Примеры**
2019-01-29 18:22:12 +00:00
``` sql
2019-01-22 18:22:16 +00:00
INDEX b (u64 * length(str), i32 + f64 * 100, date, str) TYPE minmax GRANULARITY 4
2019-02-06 20:08:43 +00:00
INDEX b (u64 * length(str), i32 + f64 * 100, date, str) TYPE set(100) GRANULARITY 4
2019-01-21 18:35:29 +00:00
```
#### Поддержка для функций {#functions-support}
Условия в секции `WHERE` содержат вызовы функций, оперирующих со столбцами. Если столбец - часть индекса, ClickHouse пытается использовать индекс при выполнении функции. Для разных видов индексов, ClickHouse поддерживает различные наборы функций, которые могут использоваться индексами.
Индекс `set` используется со всеми функциями. Наборы функций для остальных индексов представлены в таблице ниже.
2020-10-13 17:23:29 +00:00
| Функция (оператор) / Индекс | primary key | minmax | ngrambf_v1 | tokenbf_v1 | bloom_filter |
|------------------------------------------------------------------------------------------------------------|-------------|--------|-------------|-------------|---------------|
| [equals (=, ==)](../../../sql-reference/functions/comparison-functions.md#function-equals) | ✔ | ✔ | ✔ | ✔ | ✔ |
| [notEquals(!=, \<\>)](../../../sql-reference/functions/comparison-functions.md#function-notequals) | ✔ | ✔ | ✔ | ✔ | ✔ |
| [like](../../../sql-reference/functions/string-search-functions.md#function-like) | ✔ | ✔ | ✔ | ✔ | ✗ |
| [notLike](../../../sql-reference/functions/string-search-functions.md#function-notlike) | ✔ | ✔ | ✔ | ✔ | ✗ |
| [startsWith](../../../sql-reference/functions/string-functions.md#startswith) | ✔ | ✔ | ✔ | ✔ | ✗ |
| [endsWith](../../../sql-reference/functions/string-functions.md#endswith) | ✗ | ✗ | ✔ | ✔ | ✗ |
| [multiSearchAny](../../../sql-reference/functions/string-search-functions.md#function-multisearchany) | ✗ | ✗ | ✔ | ✗ | ✗ |
| [in](../../../sql-reference/functions/in-functions.md#in-functions) | ✔ | ✔ | ✔ | ✔ | ✔ |
| [notIn](../../../sql-reference/functions/in-functions.md#in-functions) | ✔ | ✔ | ✔ | ✔ | ✔ |
| [less (\<)](../../../sql-reference/functions/comparison-functions.md#function-less) | ✔ | ✔ | ✗ | ✗ | ✗ |
| [greater (\>)](../../../sql-reference/functions/comparison-functions.md#function-greater) | ✔ | ✔ | ✗ | ✗ | ✗ |
| [lessOrEquals (\<=)](../../../sql-reference/functions/comparison-functions.md#function-lessorequals) | ✔ | ✔ | ✗ | ✗ | ✗ |
| [greaterOrEquals (\>=)](../../../sql-reference/functions/comparison-functions.md#function-greaterorequals) | ✔ | ✔ | ✗ | ✗ | ✗ |
| [empty](../../../sql-reference/functions/array-functions.md#function-empty) | ✔ | ✔ | ✗ | ✗ | ✗ |
| [notEmpty](../../../sql-reference/functions/array-functions.md#function-notempty) | ✔ | ✔ | ✗ | ✗ | ✗ |
| hasToken | ✗ | ✗ | ✗ | ✔ | ✗ |
Функции с постоянным агрументом, который меньше, чем размер ngram не могут использовать индекс `ngrambf_v1` для оптимизации запроса.
Фильтры Блума могут иметь ложнопозитивные срабатывания, следовательно индексы `ngrambf_v1`, `tokenbf_v1` и `bloom_filter` невозможно использовать для оптимизации запросов, в которых результат функции предполается false, например:
- Можно оптимизировать:
- `s LIKE '%test%'`
- `NOT s NOT LIKE '%test%'`
- `s = 1`
- `NOT s != 1`
- `startsWith(s, 'test')`
- Нельзя оптимизировать:
- `NOT s LIKE '%test%'`
- `s NOT LIKE '%test%'`
- `NOT s = 1`
- `s != 1`
- `NOT startsWith(s, 'test')`
2021-08-16 01:57:09 +00:00
## Проекции {#projections}
Проекции похожи на [материализованные представления](../../sql-reference/statements/create/view.md#materialized), но определяются на уровне кусков данных. Это обеспечивает гарантии согласованности данных наряду с автоматическим использованием в запросах.
2021-08-12 21:59:16 +00:00
2021-08-16 01:57:09 +00:00
Проекции это экспериментальная возможность. Чтобы включить поддержку проекций, установите настройку [allow_experimental_projection_optimization](../../../operations/settings/settings.md#allow-experimental-projection-optimization) в значение `1`. См. также настройку [force_optimize_projection ](../../../operations/settings/settings.md#force_optimize_projection).
2021-08-12 21:59:16 +00:00
2021-08-16 01:58:10 +00:00
Проекции не поддерживаются для запросов `SELECT` с модификатором [FINAL](../../../sql-reference/statements/select/from.md#select-from-final).
2021-08-16 01:57:09 +00:00
### Запрос проекции {#projection-query}
Запрос проекции — это то, что определяет проекцию. Такой запрос неявно выбирает данные из родительской таблицы. Он имеет следующий синтаксис:
2021-08-12 21:59:16 +00:00
2021-08-16 01:57:09 +00:00
```sql
SELECT <column list expr> [GROUP BY] <group keys expr> [ORDER BY] <expr>
```
Проекции можно изменить или удалить с помощью запроса [ALTER](../../../sql-reference/statement/alter/projection.md).
2021-08-12 21:59:16 +00:00
2021-08-16 01:57:09 +00:00
### Хранение проекции {#projection-storage}
Проекции хранятся в каталоге куска данных. Это похоже на хранение индексов, но используется подкаталог, в котором хранится анонимный кусок таблицы `MergeTree`. Таблица создается запросом определения проекции. Если есть секция `GROUP BY`, то используется движок [AggregatingMergeTree](aggregatingmergetree.md), а все агрегатные функции преобразуются в `AggregateFunction`. Если есть секция `ORDER BY`, таблица `MergeTree` использует ее в качестве выражения для первичного ключа. Во время процесса слияния кусок данных проекции объединяется с помощью процедуры слияния ее хранилища. Контрольная сумма куска данных родительской таблицы включает кусок данных проекции. Другие процедуры аналогичны индексам пропуска данных.
2021-08-12 21:59:16 +00:00
2021-08-16 01:57:09 +00:00
### Анализ запросов {#projection-query-analysis}
1. Проверьте, можно ли использовать проекцию в данном запросе, то есть, что с ней выходит тот же результат, что и с запросом к базовой таблице.
2. Выберите наиболее подходящее совпадение, содержащее наименьшее количество гранул для чтения.
3. План запроса, который использует проекции, отличается от того, который использует исходные куски данных. При отсутствии проекции в некоторых кусках можно расширить план, чтобы «проецировать» на лету.
2021-08-12 21:59:16 +00:00
2021-03-06 11:13:14 +00:00
## Конкурентный доступ к данным {#concurrent-data-access}
2018-08-21 07:54:37 +00:00
Для конкурентного доступа к таблице используется мультиверсионность. То есть, при одновременном чтении и обновлении таблицы, данные будут читаться из набора кусочков, актуального на момент запроса. Длинных блокировок нет. Вставки никак не мешают чтениям.
2018-08-21 07:54:37 +00:00
Чтения из таблицы автоматически распараллеливаются.
## TTL для столбцов и таблиц {#table_engine-mergetree-ttl}
Определяет время жизни значений, а также правила перемещения данных на другой диск или том.
Секция `TTL` может быть установлена как для всей таблицы, так и для каждого отдельного столбца. Правила `TTL` для таблицы позволяют указать целевые диски или тома для фонового перемещения на них частей данных.
Выражения должны возвращать тип [Date](../../../engines/table-engines/mergetree-family/mergetree.md) или [DateTime](../../../engines/table-engines/mergetree-family/mergetree.md).
Для задания времени жизни столбца, например:
``` sql
TTL time_column
TTL time_column + interval
```
Чтобы задать `interval`, используйте операторы [интервала времени](../../../engines/table-engines/mergetree-family/mergetree.md#operators-datetime).
``` sql
TTL date_time + INTERVAL 1 MONTH
TTL date_time + INTERVAL 15 HOUR
```
### TTL столбца {#mergetree-column-ttl}
Когда срок действия значений в столбце истечет, ClickHouse заменит их значениями по умолчанию для типа данных столбца. Если срок действия всех значений столбцов в части данных истек, ClickHouse удаляет столбец из куска данных в файловой системе.
Секцию `TTL` нельзя использовать для ключевых столбцов.
2019-09-06 15:16:14 +00:00
Примеры:
Создание таблицы с TTL
``` sql
CREATE TABLE example_table
2019-09-06 15:16:14 +00:00
(
d DateTime,
a Int TTL d + INTERVAL 1 MONTH,
b Int TTL d + INTERVAL 1 MONTH,
2019-09-06 15:16:14 +00:00
c String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d;
```
2019-09-06 15:16:14 +00:00
Добавление TTL на колонку существующей таблицы
2019-09-06 15:16:14 +00:00
``` sql
2019-09-06 15:26:51 +00:00
ALTER TABLE example_table
2019-09-06 15:16:14 +00:00
MODIFY COLUMN
c String TTL d + INTERVAL 1 DAY;
```
2019-09-06 15:16:14 +00:00
Изменение TTL у колонки
``` sql
2019-09-06 15:26:51 +00:00
ALTER TABLE example_table
2019-09-06 15:16:14 +00:00
MODIFY COLUMN
c String TTL d + INTERVAL 1 MONTH;
2019-09-06 15:16:14 +00:00
```
### TTL таблицы {#mergetree-table-ttl}
Для таблицы можно задать одно выражение для устаревания данных, а также несколько выражений, по срабатывании которых данные переместятся на [некоторый диск или том](#table_engine-mergetree-multiple-volumes). Когда некоторые данные в таблице устаревают, ClickHouse удаляет все соответствующие строки.
``` sql
2021-06-01 14:23:46 +00:00
TTL expr
2021-01-23 18:16:59 +00:00
[DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'][, DELETE|TO DISK 'aaa'|TO VOLUME 'bbb'] ...
2021-06-01 14:23:46 +00:00
[WHERE conditions]
[GROUP BY key_expr [SET v1 = aggr_func(v1) [, v2 = aggr_func(v2) ...]] ]
```
За каждым TTL выражением может следовать тип действия, которое выполняется после достижения времени, соответствующего результату TTL выражения:
- `DELETE` - удалить данные (действие по умолчанию);
- `TO DISK 'aaa'` - переместить данные на диск `aaa`;
2021-02-01 23:44:40 +00:00
- `TO VOLUME 'bbb'` - переместить данные на том `bbb`;
- `GROUP BY` - агрегировать данные.
2021-02-01 23:44:40 +00:00
В секции `WHERE` можно задать условие удаления или агрегирования устаревших строк (для перемещения условие `WHERE` не применимо).
2021-01-23 18:16:59 +00:00
2021-06-01 14:23:46 +00:00
Колонки, по которым агрегируются данные в `GROUP BY`, должны являться префиксом первичного ключа таблицы.
2021-01-23 18:16:59 +00:00
2021-02-01 23:44:40 +00:00
Если колонка не является частью выражения `GROUP BY` и не задается напрямую в секции `SET`, в результирующих строках она будет содержать случайное значение, взятое из одной из сгруппированных строк (как будто к ней применяется агрегирующая функция `any`).
2021-01-23 18:16:59 +00:00
**Примеры**
2021-06-01 14:23:46 +00:00
Создание таблицы с TTL:
2019-09-06 15:16:14 +00:00
``` sql
CREATE TABLE example_table
2019-09-06 15:16:14 +00:00
(
d DateTime,
a Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d
TTL d + INTERVAL 1 MONTH [DELETE],
d + INTERVAL 1 WEEK TO VOLUME 'aaa',
d + INTERVAL 2 WEEK TO DISK 'bbb';
```
2019-09-06 15:16:14 +00:00
2021-01-23 18:16:59 +00:00
Изменение TTL:
2019-09-06 15:16:14 +00:00
``` sql
2019-09-06 15:26:51 +00:00
ALTER TABLE example_table
MODIFY TTL d + INTERVAL 1 DAY;
2019-09-06 15:16:14 +00:00
```
2021-01-23 18:16:59 +00:00
Создание таблицы, в которой строки устаревают через месяц. Устаревшие строки удаляются, если дата выпадает на понедельник:
``` sql
CREATE TABLE table_with_where
(
2021-06-01 14:23:46 +00:00
d DateTime,
2021-01-23 18:16:59 +00:00
a Int
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(d)
ORDER BY d
TTL d + INTERVAL 1 MONTH DELETE WHERE toDayOfWeek(d) = 1;
```
Создание таблицы, где устаревшие строки агрегируются. В результирующих строках колонка `x` содержит максимальное значение по сгруппированным строкам, `y` — минимальное значение, а `d` — случайное значение из одной из сгуппированных строк.
``` sql
CREATE TABLE table_for_aggregation
(
2021-06-01 14:23:46 +00:00
d DateTime,
k1 Int,
k2 Int,
x Int,
2021-01-23 18:16:59 +00:00
y Int
)
ENGINE = MergeTree
2021-03-12 18:13:20 +00:00
ORDER BY (k1, k2)
2021-01-23 18:16:59 +00:00
TTL d + INTERVAL 1 MONTH GROUP BY k1, k2 SET x = max(x), y = min(y);
```
**Удаление данных**
Данные с истекшим TTL удаляются, когда ClickHouse мёржит куски данных.
DOCS-624: Fixing links to nowhere (#10675) * enbaskakova-DOCSUP-652 (#101) * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: BayoNet <da-daos@yandex.ru> * Revert "enbaskakova-DOCSUP-652 (#101)" (#107) This reverts commit 639fee7610f28e421d14e535b7def3f466e7efca. * CLICKHOUSEDOCS-624: Fixed links. Was 60, became 13. * CLICKHOUSEDOCS-624: Finished fix links in Enlish version. * CLICKHOUSEDOCS-624: Fixed RU links Co-authored-by: elenaspb2019 <47083263+elenaspb2019@users.noreply.github.com> Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: Sergei Shtykov <bayonet@yandex-team.ru>
2020-05-06 06:13:29 +00:00
Когда ClickHouse видит, что некоторые данные устарели, он выполняет внеплановые мёржи. Для управление частотой подобных мёржей, можно задать настройку `merge_with_ttl_timeout`. Если её значение слишком низкое, придется выполнять много внеплановых мёржей, которые могут начать потреблять значительную долю ресурсов сервера.
Если вы выполните запрос `SELECT` между слияниями вы можете получить устаревшие данные. Чтобы избежать этого используйте запрос [OPTIMIZE](../../../engines/table-engines/mergetree-family/mergetree.md#misc_operations-optimize) перед `SELECT`.
## Хранение данных таблицы на нескольких блочных устройствах {#table_engine-mergetree-multiple-volumes}
2019-09-12 17:31:19 +00:00
2021-03-06 11:13:14 +00:00
### Введение {#introduction}
Движки таблиц семейства `MergeTree` могут хранить данные на нескольких блочных устройствах. Это может оказаться полезным, например, при неявном разделении данных одной таблицы на «горячие» и «холодные». Наиболее свежая часть занимает малый объём и запрашивается регулярно, а большой хвост исторических данных запрашивается редко. При наличии в системе нескольких дисков, «горячая» часть данных может быть размещена на быстрых дисках (например, на NVMe SSD или в памяти), а холодная на более медленных (например, HDD).
2019-09-13 10:44:10 +00:00
Минимальной перемещаемой единицей для `MergeTree` является кусок данных (data part). Данные одного куска могут находится только на одном диске. Куски могут перемещаться между дисками в фоне, согласно пользовательским настройкам, а также с помощью запросов [ALTER](../../../engines/table-engines/mergetree-family/mergetree.md#alter_move-partition).
2019-09-12 17:31:19 +00:00
2021-03-06 11:13:14 +00:00
### Термины {#terms}
2019-09-12 17:31:19 +00:00
- Диск — примонтированное в файловой системе блочное устройство.
- Диск по умолчанию — диск, на котором находится путь, указанный в конфигурационной настройке сервера [path](../../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-path).
- Том (Volume) — упорядоченный набор равноценных дисков (схоже с [JBOD](https://ru.wikipedia.org/wiki/JBOD))
- Политика хранения (StoragePolicy) — множество томов с правилами перемещения данных между ними.
2020-10-13 17:23:29 +00:00
У всех описанных сущностей при создании указываются имена, можно найти в системных таблицах [system.storage_policies](../../../engines/table-engines/mergetree-family/mergetree.md#system_tables-storage_policies) и [system.disks](../../../engines/table-engines/mergetree-family/mergetree.md#system_tables-disks). Имя политики хранения можно указать в настройке `storage_policy` движков таблиц семейства `MergeTree`.
2019-09-12 17:31:19 +00:00
DOCS-624: Fixing links to nowhere (#10675) * enbaskakova-DOCSUP-652 (#101) * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * Update docs/en/sql_reference/aggregate_functions/combinators.md Co-Authored-By: BayoNet <da-daos@yandex.ru> * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" * "docs(orNull&orDefault): Functions 'orNull&orDefault' have been edited" Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: BayoNet <da-daos@yandex.ru> * Revert "enbaskakova-DOCSUP-652 (#101)" (#107) This reverts commit 639fee7610f28e421d14e535b7def3f466e7efca. * CLICKHOUSEDOCS-624: Fixed links. Was 60, became 13. * CLICKHOUSEDOCS-624: Finished fix links in Enlish version. * CLICKHOUSEDOCS-624: Fixed RU links Co-authored-by: elenaspb2019 <47083263+elenaspb2019@users.noreply.github.com> Co-authored-by: elenbaskakova <elenbaskakova@yandex-team.ru> Co-authored-by: Sergei Shtykov <bayonet@yandex-team.ru>
2020-05-06 06:13:29 +00:00
### Конфигурация {#table_engine-mergetree-multiple-volumes_configure}
2019-09-12 17:31:19 +00:00
Диски, тома и политики хранения задаются внутри тега `<storage_configuration>` в основном файле `config.xml` или в отдельном файле в директории `config.d`.
Структура конфигурации:
2019-09-12 17:31:19 +00:00
``` xml
<storage_configuration>
<disks>
<disk_name_1> <!-- disk name -->
<path>/mnt/fast_ssd/clickhouse/</path>
</disk_name_1>
<disk_name_2>
<path>/mnt/hdd1/clickhouse/</path>
<keep_free_space_bytes>10485760</keep_free_space_bytes>
</disk_name_2>
<disk_name_3>
<path>/mnt/hdd2/clickhouse/</path>
<keep_free_space_bytes>10485760</keep_free_space_bytes>
</disk_name_3>
...
</disks>
2019-09-12 17:31:19 +00:00
...
</storage_configuration>
2019-09-12 17:31:19 +00:00
```
2019-09-13 13:15:19 +00:00
Теги:
2019-09-13 13:15:19 +00:00
- `<disk_name_N>` — имя диска. Имена должны быть разными для всех дисков.
- `path` — путь по которому будут храниться данные сервера (каталоги `data` и `shadow`), должен быть терминирован `/`.
- `keep_free_space_bytes` — размер зарезервированного свободного места на диске.
2019-09-12 17:31:19 +00:00
Порядок задания дисков не имеет значения.
Общий вид конфигурации политик хранения:
``` xml
<storage_configuration>
...
<policies>
<policy_name_1>
<volumes>
<volume_name_1>
<disk>disk_name_from_disks_configuration</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</volume_name_1>
<volume_name_2>
<!-- configuration -->
</volume_name_2>
<!-- more volumes -->
</volumes>
<move_factor>0.2</move_factor>
</policy_name_1>
<policy_name_2>
<!-- configuration -->
</policy_name_2>
<!-- more policies -->
</policies>
...
</storage_configuration>
```
Тэги:
- `policy_name_N` — название политики. Названия политик должны быть уникальны.
- `volume_name_N` — название тома. Названия томов должны быть уникальны.
- `disk` — диск, находящийся внутри тома.
- `max_data_part_size_bytes` — максимальный размер куска данных, который может находится на любом из дисков этого тома.
- `move_factor` — доля доступного свободного места на томе, если места становится меньше, то данные начнут перемещение на следующий том, если он есть (по умолчанию 0.1).
- `prefer_not_to_merge` — Отключает слияние кусков данных, хранящихся на данном томе. Если данная настройка включена, то слияние данных, хранящихся на данном томе, не допускается. Это позволяет контролировать работу ClickHouse с медленными дисками.
Примеры конфигураций:
2019-09-12 17:31:19 +00:00
``` xml
<storage_configuration>
...
<policies>
<hdd_in_order> <!-- policy name -->
<volumes>
<single> <!-- volume name -->
<disk>disk1</disk>
<disk>disk2</disk>
</single>
</volumes>
</hdd_in_order>
<moving_from_ssd_to_hdd>
<volumes>
<hot>
<disk>fast_ssd</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</hot>
<cold>
<disk>disk1</disk>
</cold>
</volumes>
<move_factor>0.2</move_factor>
</moving_from_ssd_to_hdd>
<small_jbod_with_external_no_merges>
<volumes>
<main>
<disk>jbod1</disk>
</main>
<external>
<disk>external</disk>
<prefer_not_to_merge>true</prefer_not_to_merge>
</external>
</volumes>
</small_jbod_with_external_no_merges>
</policies>
...
</storage_configuration>
2019-09-12 17:31:19 +00:00
```
В приведенном примере, политика `hdd_in_order` реализует прицип [round-robin](https://ru.wikipedia.org/wiki/Round-robin_(%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)). Так как в политике есть всего один том (`single`), то все записи производятся на его диски по круговому циклу. Такая политика может быть полезна при наличии в системе нескольких похожих дисков, но при этом не сконфигурирован RAID. Учтите, что каждый отдельный диск ненадёжен и чтобы не потерять важные данные это необходимо скомпенсировать за счет хранения данных в трёх копиях.
2019-09-12 17:31:19 +00:00
Если система содержит диски различных типов, то может пригодиться политика `moving_from_ssd_to_hdd`. В томе `hot` находится один SSD-диск (`fast_ssd`), а также задается ограничение на максимальный размер куска, который может храниться на этом томе (1GB). Все куски такой таблицы больше 1GB будут записываться сразу на том `cold`, в котором содержится один HDD-диск `disk1`. Также, при заполнении диска `fast_ssd` более чем на 80% данные будут переносится на диск `disk1` фоновым процессом.
2019-09-13 13:15:19 +00:00
2019-09-13 10:44:10 +00:00
Порядок томов в политиках хранения важен, при достижении условий на переполнение тома данные переносятся на следующий. Порядок дисков в томах так же важен, данные пишутся по очереди на каждый из них.
2019-09-12 17:31:19 +00:00
После задания конфигурации политик хранения их можно использовать, как настройку при создании таблиц:
2019-09-12 17:31:19 +00:00
``` sql
2019-09-12 17:31:19 +00:00
CREATE TABLE table_with_non_default_policy (
EventDate Date,
OrderID UInt64,
BannerID UInt64,
SearchPhrase String
) ENGINE = MergeTree
2019-09-12 17:31:19 +00:00
ORDER BY (OrderID, BannerID)
PARTITION BY toYYYYMM(EventDate)
SETTINGS storage_policy = 'moving_from_ssd_to_hdd'
2019-09-12 17:31:19 +00:00
```
2021-06-17 08:46:42 +00:00
По умолчанию используется политика хранения `default` в которой есть один том и один диск, указанный в `<path>`.
Изменить политику хранения после создания таблицы можно при помощи запроса [ALTER TABLE ... MODIFY SETTING]. При этом необходимо учесть, что новая политика должна содержать все тома и диски предыдущей политики с теми же именами.
2019-09-12 17:31:19 +00:00
Количество потоков для фоновых перемещений кусков между дисками можно изменить с помощью настройки [background_move_pool_size](../../../operations/settings/settings.md#background_move_pool_size)
2021-03-12 10:00:46 +00:00
### Особенности работы {#details}
В таблицах `MergeTree` данные попадают на диск несколькими способами:
- В результате вставки (запрос `INSERT`).
- В фоновых операциях слияний и [мутаций](../../../sql-reference/statements/alter/index.md#mutations).
- При скачивании данных с другой реплики.
- В результате заморозки партиций [ALTER TABLE … FREEZE PARTITION](../../../engines/table-engines/mergetree-family/mergetree.md#alter_freeze-partition).
Во всех случаях, кроме мутаций и заморозки партиций, при записи куска выбирается том и диск в соответствии с указанной конфигурацией хранилища:
1. Выбирается первый по порядку том, на котором есть свободное место для записи куска (`unreserved_space > current_part_size`) и который позволяет записывать куски требуемого размера `max_data_part_size_bytes > current_part_size`.
2. Внутри тома выбирается следующий диск после того, на который была предыдущая запись и на котором свободного места больше чем размер куска (`unreserved_space - keep_free_space_bytes > current_part_size`)
Мутации и запросы заморозки партиций в реализации используют [жесткие ссылки](https://ru.wikipedia.org/wiki/%D0%96%D1%91%D1%81%D1%82%D0%BA%D0%B0%D1%8F_%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0). Жесткие ссылки между различными дисками не поддерживаются, поэтому в случае таких операций куски размещаются на тех же дисках, что и исходные.
В фоне куски перемещаются между томами на основе информации о занятом месте (настройка `move_factor`) по порядку, в котором указаны тома в конфигурации. Данные никогда не перемещаются с последнего тома и на первый том. Следить за фоновыми перемещениями можно с помощью системных таблиц [system.part_log](../../../engines/table-engines/mergetree-family/mergetree.md#system_tables-part-log) (поле `type = MOVE_PART`) и [system.parts](../../../engines/table-engines/mergetree-family/mergetree.md#system_tables-parts) (поля `path` и `disk`). Также подробная информация о перемещениях доступна в логах сервера.
С помощью запроса [ALTER TABLE … MOVE PART\|PARTITION … TO VOLUME\|DISK …](../../../engines/table-engines/mergetree-family/mergetree.md#alter_move-partition) пользователь может принудительно перенести кусок или партицию с одного раздела на другой. При этом учитываются все ограничения, указанные для фоновых операций. Запрос самостоятельно инициирует процесс перемещения не дожидаясь фоновых операций. В случае недостатка места или неудовлетворения ограничениям пользователь получит сообщение об ошибке.
Перемещения данных не взаимодействуют с репликацией данных, поэтому на разных репликах одной и той же таблицы могут быть указаны разные политики хранения.
После выполнения фоновых слияний или мутаций старые куски не удаляются сразу, а через некоторое время (табличная настройка `old_parts_lifetime`). Также они не перемещаются на другие тома или диски, поэтому до момента удаления они продолжают учитываться при подсчёте занятого дискового пространства.
2021-03-06 11:13:14 +00:00
## Использование сервиса S3 для хранения данных {#table_engine-mergetree-s3}
Таблицы семейства `MergeTree` могут хранить данные в сервисе [S3](https://aws.amazon.com/s3/) при использовании диска типа `s3`.
2021-03-06 11:13:14 +00:00
Конфигурация:
``` xml
<storage_configuration>
...
<disks>
<s3>
<type>s3</type>
<endpoint>https://storage.yandexcloud.net/my-bucket/root-path/</endpoint>
<access_key_id>your_access_key_id</access_key_id>
<secret_access_key>your_secret_access_key</secret_access_key>
2021-05-01 17:41:31 +00:00
<region></region>
2021-03-06 11:13:14 +00:00
<proxy>
<uri>http://proxy1</uri>
<uri>http://proxy2</uri>
</proxy>
<connect_timeout_ms>10000</connect_timeout_ms>
<request_timeout_ms>5000</request_timeout_ms>
<retry_attempts>10</retry_attempts>
2021-06-01 14:23:46 +00:00
<single_read_retries>4</single_read_retries>
2021-03-06 11:13:14 +00:00
<min_bytes_for_seek>1000</min_bytes_for_seek>
<metadata_path>/var/lib/clickhouse/disks/s3/</metadata_path>
<cache_enabled>true</cache_enabled>
<cache_path>/var/lib/clickhouse/disks/s3/cache/</cache_path>
<skip_access_check>false</skip_access_check>
</s3>
</disks>
...
</storage_configuration>
```
Обязательные параметры:
2021-03-06 11:55:17 +00:00
- `endpoint` — URL точки приема запроса на стороне S3 в [форматах](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html) `path` или `virtual hosted`. URL точки должен содержать бакет и путь к корневой директории на сервере, где хранятся данные.
2021-06-01 14:23:46 +00:00
- `access_key_id` — id ключа доступа к S3.
2021-03-06 11:13:14 +00:00
- `secret_access_key` — секретный ключ доступа к S3.
2021-06-01 14:23:46 +00:00
Необязательные параметры:
2021-03-06 11:55:17 +00:00
2021-05-01 17:41:31 +00:00
- `region` — название региона S3.
2021-03-30 00:32:26 +00:00
- `use_environment_credentials` — признак, нужно ли считывать учетные данные AWS из сетевого окружения, а также из переменных окружения `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` и `AWS_SESSION_TOKEN`, если они есть. Значение по умолчанию: `false`.
- `use_insecure_imds_request` — признак, нужно ли использовать менее безопасное соединение при выполнении запроса к IMDS при получении учётных данных из метаданных Amazon EC2. Значение по умолчанию: `false`.
2021-06-01 14:23:46 +00:00
- `proxy` — конфигурация прокси-сервера для конечной точки S3. Каждый элемент `uri` внутри блока `proxy` должен содержать URL прокси-сервера.
- `connect_timeout_ms` — таймаут подключения к сокету в миллисекундах. Значение по умолчанию: 10 секунд.
- `request_timeout_ms` — таймаут выполнения запроса в миллисекундах. Значение по умолчанию: 5 секунд.
- `retry_attempts` — число попыток выполнения запроса в случае возникновения ошибки. Значение по умолчанию: `10`.
- `single_read_retries` — число попыток выполнения запроса в случае возникновения ошибки в процессе чтения. Значение по умолчанию: `4`.
- `min_bytes_for_seek` — минимальное количество байтов, которые используются для операций поиска вместо последовательного чтения. Значение по умолчанию: 1 МБайт.
- `metadata_path` — путь к локальному файловому хранилищу для хранения файлов с метаданными для S3. Значение по умолчанию: `/var/lib/clickhouse/disks/<disk_name>/`.
- `cache_enabled` — признак, разрешено ли хранение кэша засечек и файлов индекса в локальной файловой системе. Значение по умолчанию: `true`.
- `cache_path` — путь в локальной файловой системе, где будут храниться кэш засечек и файлы индекса. Значение по умолчанию: `/var/lib/clickhouse/disks/<disk_name>/cache/`.
- `skip_access_check` — признак, выполнять ли проверку доступов при запуске диска. Если установлено значение `true`, то проверка не выполняется. Значение по умолчанию: `false`.
2021-03-06 11:13:14 +00:00
Диск S3 может быть сконфигурирован как `main` или `cold`:
2021-03-06 11:55:17 +00:00
2021-03-06 11:13:14 +00:00
``` xml
<storage_configuration>
...
<disks>
<s3>
<type>s3</type>
<endpoint>https://storage.yandexcloud.net/my-bucket/root-path/</endpoint>
<access_key_id>your_access_key_id</access_key_id>
<secret_access_key>your_secret_access_key</secret_access_key>
</s3>
</disks>
<policies>
<s3_main>
<volumes>
<main>
<disk>s3</disk>
</main>
</volumes>
</s3_main>
<s3_cold>
<volumes>
<main>
<disk>default</disk>
</main>
<external>
<disk>s3</disk>
</external>
</volumes>
<move_factor>0.2</move_factor>
</s3_cold>
</policies>
...
</storage_configuration>
```
2021-06-01 14:23:46 +00:00
Если диск сконфигурирован как `cold`, данные будут переноситься в S3 при срабатывании правил TTL или когда свободное место на локальном диске станет меньше порогового значения, которое определяется как `move_factor * disk_size`.
## Использование сервиса HDFS для хранения данных {#table_engine-mergetree-hdfs}
[HDFS](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html) — это распределенная файловая система для удаленного хранения данных.
Таблицы семейства `MergeTree` могут хранить данные в сервисе HDFS при использовании диска типа `HDFS`.
Пример конфигурации:
``` xml
<yandex>
<storage_configuration>
<disks>
<hdfs>
<type>hdfs</type>
<endpoint>hdfs://hdfs1:9000/clickhouse/</endpoint>
</hdfs>
</disks>
<policies>
<hdfs>
<volumes>
<main>
<disk>hdfs</disk>
</main>
</volumes>
</hdfs>
</policies>
</storage_configuration>
<merge_tree>
<min_bytes_for_wide_part>0</min_bytes_for_wide_part>
</merge_tree>
</yandex>
```
Обязательные параметры:
- `endpoint` — URL точки приема запроса на стороне HDFS в формате `path`. URL точки должен содержать путь к корневой директории на сервере, где хранятся данные.
Необязательные параметры:
- `min_bytes_for_seek` — минимальное количество байтов, которые используются для операций поиска вместо последовательного чтения. Значение по умолчанию: 1 МБайт.