Merge branch 'master' into control-heavy-builds

This commit is contained in:
Nikolai Kochetov 2020-09-21 17:09:33 +03:00
commit 8a3549ebd3
56 changed files with 722 additions and 195 deletions

View File

@ -1,7 +1,7 @@
# docker build -t yandex/clickhouse-test-base .
FROM ubuntu:19.10
ENV DEBIAN_FRONTEND=noninteractive LLVM_VERSION=10
ENV DEBIAN_FRONTEND=noninteractive LLVM_VERSION=11
RUN apt-get update \
&& apt-get install ca-certificates lsb-release wget gnupg apt-transport-https \
@ -43,7 +43,6 @@ RUN apt-get update \
llvm-${LLVM_VERSION} \
moreutils \
perl \
perl \
pigz \
pkg-config \
tzdata \

View File

@ -1,5 +1,5 @@
# docker build -t yandex/clickhouse-integration-test .
FROM ubuntu:19.10
FROM yandex/clickhouse-test-base
RUN apt-get update \
&& env DEBIAN_FRONTEND=noninteractive apt-get -y install \
@ -8,7 +8,6 @@ RUN apt-get update \
libreadline-dev \
libicu-dev \
bsdutils \
llvm-9 \
gdb \
unixodbc \
odbcinst \
@ -29,9 +28,3 @@ RUN curl 'https://cdn.mysql.com//Downloads/Connector-ODBC/8.0/mysql-connector-od
ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Sanitizer options
RUN echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment; \
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \
echo "MSAN_OPTIONS='abort_on_error=1'" >> /etc/environment; \
ln -s /usr/lib/llvm-9/bin/llvm-symbolizer /usr/bin/llvm-symbolizer;

View File

@ -45,7 +45,7 @@ Action required for every item -- these are errors that must be fixed.
This table shows queries that take significantly longer to process on the client than on the server. A possible reason might be sending too much data to the client, e.g., a forgotten `format Null`.
#### Inconsistent Short Marking
#### Unexpected Query Duration
Action required for every item -- these are errors that must be fixed.
Queries that have "short" duration (on the order of 0.1 s) can't be reliably tested in a normal way, where we perform a small (about ten) measurements for each server, because the signal-to-noise ratio is much smaller. There is a special mode for such queries that instead runs them for a fixed amount of time, normally with much higher number of measurements (up to thousands). This mode must be explicitly enabled by the test author to avoid accidental errors. It must be used only for queries that are meant to complete "immediately", such as `select count(*)`. If your query is not supposed to be "immediate", try to make it run longer, by e.g. processing more data.

View File

@ -688,12 +688,13 @@ create view shortness
-- Report of queries that have inconsistent 'short' markings:
-- 1) have short duration, but are not marked as 'short'
-- 2) the reverse -- marked 'short' but take too long.
-- The threshold for 2) is twice the threshold for 1), to avoid jitter.
-- The threshold for 2) is significantly larger than the threshold for 1), to
-- avoid jitter.
create table inconsistent_short_marking_report
engine File(TSV, 'report/inconsistent-short-marking.tsv')
engine File(TSV, 'report/unexpected-query-duration.tsv')
as select
multiIf(marked_short and time > 0.1, 'marked as short but is too long',
not marked_short and time < 0.02, 'is short but not marked as such',
multiIf(marked_short and time > 0.1, '"short" queries must run faster than 0.02 s',
not marked_short and time < 0.02, '"normal" queries must run longer than 0.1 s',
'') problem,
marked_short, time,
test, query_index, query_display_name

View File

@ -98,9 +98,9 @@ th {{
tr:nth-child(odd) td {{filter: brightness(90%);}}
.inconsistent-short-marking tr :nth-child(2),
.inconsistent-short-marking tr :nth-child(3),
.inconsistent-short-marking tr :nth-child(5),
.unexpected-query-duration tr :nth-child(2),
.unexpected-query-duration tr :nth-child(3),
.unexpected-query-duration tr :nth-child(5),
.all-query-times tr :nth-child(1),
.all-query-times tr :nth-child(2),
.all-query-times tr :nth-child(3),
@ -325,13 +325,13 @@ if args.report == 'main':
if slow_on_client_rows:
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries are taking noticeable time client-side (missing `FORMAT Null`?)</a>']);
unmarked_short_rows = tsvRows('report/inconsistent-short-marking.tsv')
unmarked_short_rows = tsvRows('report/unexpected-query-duration.tsv')
error_tests += len(unmarked_short_rows)
addSimpleTable('Inconsistent Short Marking',
['Problem', 'Is marked as short', 'New client time, s', 'Test', '#', 'Query'],
addSimpleTable('Unexpected Query Duration',
['Problem', 'Marked as "short"?', 'Run time, s', 'Test', '#', 'Query'],
unmarked_short_rows)
if unmarked_short_rows:
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries have inconsistent short marking</a>']);
errors_explained.append([f'<a href="#{currentTableAnchor()}">Some queries have unexpected duration</a>']);
def add_partial():
rows = tsvRows('report/partial-queries-report.tsv')

View File

@ -48,13 +48,6 @@ fi
ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml
echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
service zookeeper start
sleep 5
service clickhouse-server start && sleep 5

View File

@ -48,13 +48,6 @@ fi
ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml
echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-10/bin/llvm-symbolizer" >> /etc/environment
service zookeeper start
sleep 5
service clickhouse-server start && sleep 5

View File

@ -43,8 +43,6 @@ ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/u
ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/
ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/
echo "TSAN_OPTIONS='halt_on_error=1 history_size=7 ignore_noninstrumented_modules=1 verbosity=1'" >> /etc/environment
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment
echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment
start

View File

@ -5,12 +5,5 @@ ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get install gdb
CMD ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer; \
echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \
echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \
echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer" >> /etc/environment; \
echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \
service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; \
CMD service zookeeper start && sleep 7 && /usr/share/zookeeper/bin/zkCli.sh -server localhost:2181 -create create /clickhouse_test ''; \
gdb -q -ex 'set print inferior-events off' -ex 'set confirm off' -ex 'set print thread-events off' -ex run -ex bt -ex quit --args ./unit_tests_dbms | tee test_output/test_result.txt

View File

@ -521,6 +521,22 @@ For more information, see the MergeTreeSettings.h header file.
</merge_tree>
```
## replicated\_merge\_tree {#server_configuration_parameters-replicated_merge_tree}
Fine tuning for tables in the [ReplicatedMergeTree](../../engines/table-engines/mergetree-family/mergetree.md).
This setting has higher priority.
For more information, see the MergeTreeSettings.h header file.
**Example**
``` xml
<replicated_merge_tree>
<max_suspicious_broken_parts>5</max_suspicious_broken_parts>
</replicated_merge_tree>
```
## openSSL {#server_configuration_parameters-openssl}
SSL client/server configuration.

View File

@ -1817,7 +1817,7 @@ Default value: 8192.
Turns on or turns off using of single dictionary for the data part.
By default, ClickHouse server monitors the size of dictionaries and if a dictionary overflows then the server starts to write the next one. To prohibit creating several dictionaries set `low_cardinality_use_single_dictionary_for_part = 1`.
By default, the ClickHouse server monitors the size of dictionaries and if a dictionary overflows then the server starts to write the next one. To prohibit creating several dictionaries set `low_cardinality_use_single_dictionary_for_part = 1`.
Possible values:

View File

@ -21,7 +21,7 @@ LowCardinality(data_type)
`LowCardinality` is a superstructure that changes a data storage method and rules of data processing. ClickHouse applies [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) to `LowCardinality`-columns. Operating with dictionary encoded data significantly increases performance of [SELECT](../../sql-reference/statements/select/index.md) queries for many applications.
The efficiency of using `LowCarditality` data type depends on data diversity. If a dictionary contains less than 10,000 distinct values, then ClickHouse mostly shows higher efficiency of data reading and storing. If a dictionary contains more than 100,000 distinct values, then ClickHouse can perform worse in comparison with using ordinary data types.
The efficiency of using `LowCardinality` data type depends on data diversity. If a dictionary contains less than 10,000 distinct values, then ClickHouse mostly shows higher efficiency of data reading and storing. If a dictionary contains more than 100,000 distinct values, then ClickHouse can perform worse in comparison with using ordinary data types.
Consider using `LowCardinality` instead of [Enum](../../sql-reference/data-types/enum.md) when working with strings. `LowCardinality` provides more flexibility in use and often reveals the same or higher efficiency.

View File

@ -516,7 +516,7 @@ Result:
**See Also**
- \[ISO 8601 announcement by @xkcd\](https://xkcd.com/1179/)
- [ISO 8601 announcement by @xkcd](https://xkcd.com/1179/)
- [RFC 1123](https://tools.ietf.org/html/rfc1123)
- [toDate](#todate)
- [toDateTime](#todatetime)

View File

@ -6,4 +6,14 @@ toc_title: "\u041A\u043E\u043C\u043C\u0435\u0440\u0447\u0435\u0441\u043A\u0438\u
\ \u0443\u0441\u043B\u0443\u0433\u0438"
---
# Коммерческие услуги {#clickhouse-commercial-services}
Данный раздел содержит описание коммерческих услуг, предоставляемых для ClickHouse. Поставщики этих услуг — независимые компании, которые могут не быть аффилированы с Яндексом.
Категории услуг:
- Облачные услуги [Cloud](../commercial/cloud.md)
- Поддержка [Support](../commercial/support.md)
!!! note "Для поставщиков услуг"
Если вы — представитель компании-поставщика услуг, вы можете отправить запрос на добавление вашей компании и ваших услуг в соответствующий раздел данной документации (или на добавление нового раздела, если ваши услуги не соответствуют ни одной из существующих категорий). Чтобы отправить запрос (pull-request) на добавление описания в документацию, нажмите на значок "карандаша" в правом верхнем углу страницы. Если ваши услуги доступны в только отдельных регионах, не забудьте указать это на соответствующих локализованных страницах (и обязательно отметьте это при отправке заявки).

View File

@ -43,9 +43,6 @@ ORDER BY expr
Описание параметров смотрите в [описании запроса CREATE](../../../engines/table-engines/mergetree-family/mergetree.md).
!!! note "Примечание"
`INDEX` — экспериментальная возможность, смотрите [Индексы пропуска данных](#table_engine-mergetree-data_skipping-indexes).
### Секции запроса {#mergetree-query-clauses}
- `ENGINE` — имя и параметры движка. `ENGINE = MergeTree()`. `MergeTree` не имеет параметров.
@ -269,7 +266,7 @@ ClickHouse не может использовать индекс, если зн
ClickHouse использует эту логику не только для последовательностей дней месяца, но и для любого частично-монотонного первичного ключа.
### Индексы пропуска данных (экспериментальная функциональность) {#table_engine-mergetree-data_skipping-indexes}
### Индексы пропуска данных {#table_engine-mergetree-data_skipping-indexes}
Объявление индексов при определении столбцов в запросе `CREATE`.
@ -566,7 +563,7 @@ ALTER TABLE example_table
- `volume_name_N` — название тома. Названия томов должны быть уникальны.
- `disk` — диск, находящийся внутри тома.
- `max_data_part_size_bytes` — максимальный размер куска данных, который может находится на любом из дисков этого тома.
- `move_factor` — доля свободного места, при превышении которого данные начинают перемещаться на следующий том, если он есть (по умолчанию 0.1).
- `move_factor` — доля доступного свободного места на томе, если места становится меньше, то данные начнут перемещение на следующий том, если он есть (по умолчанию 0.1).
Примеры конфигураций:

View File

@ -1050,13 +1050,13 @@ $ clickhouse-client --query="SELECT * FROM {some_table} FORMAT Parquet" > {some_
Для обмена данными с экосистемой Hadoop можно использовать движки таблиц [HDFS](../engines/table-engines/integrations/hdfs.md).
## Arrow {data-format-arrow}
## Arrow {#data-format-arrow}
[Apache Arrow](https://arrow.apache.org/) поставляется с двумя встроенными поколоночнами форматами хранения. ClickHouse поддерживает операции чтения и записи для этих форматов.
`Arrow` — это Apache Arrow's "file mode" формат. Он предназначен для произвольного доступа в памяти.
## ArrowStream {data-format-arrow-stream}
## ArrowStream {#data-format-arrow-stream}
`ArrowStream` — это Apache Arrow's "stream mode" формат. Он предназначен для обработки потоков в памяти.

View File

@ -484,7 +484,7 @@ INSERT INTO test VALUES (lower('Hello')), (lower('world')), (lower('INSERT')), (
См. также:
- [JOIN strictness](../../sql-reference/statements/select/join.md#select-join-strictness)
- [JOIN strictness](../../sql-reference/statements/select/join.md#join-settings)
## max\_block\_size {#setting-max_block_size}
@ -1616,6 +1616,63 @@ SELECT idx, i FROM null_in WHERE i IN (1, NULL) SETTINGS transform_null_in = 1;
- [Обработка значения NULL в операторе IN](../../sql-reference/operators/in.md#in-null-processing)
## low\_cardinality\_max\_dictionary\_size {#low_cardinality_max_dictionary_size}
Задает максимальный размер общего глобального словаря (в строках) для типа данных `LowCardinality`, который может быть записан в файловую систему хранилища. Настройка предотвращает проблемы с оперативной памятью в случае неограниченного увеличения словаря. Все данные, которые не могут быть закодированы из-за ограничения максимального размера словаря, ClickHouse записывает обычным способом.
Допустимые значения:
- Положительное целое число.
Значение по умолчанию: 8192.
## low\_cardinality\_use\_single\_dictionary\_for\_part {#low_cardinality_use_single_dictionary_for_part}
Включает или выключает использование единого словаря для куска (парта).
По умолчанию сервер ClickHouse следит за размером словарей, и если словарь переполняется, сервер создает следующий. Чтобы запретить создание нескольких словарей, задайте настройку `low_cardinality_use_single_dictionary_for_part = 1`.
Допустимые значения:
- 1 — Создание нескольких словарей для частей данных запрещено.
- 0 — Создание нескольких словарей для частей данных не запрещено.
Значение по умолчанию: 0.
## low\_cardinality\_allow\_in\_native\_format {#low_cardinality_allow_in_native_format}
Разрешает или запрещает использование типа данных `LowCardinality` с форматом данных [Native](../../interfaces/formats.md#native).
Если использование типа `LowCardinality` ограничено, сервер CLickHouse преобразует столбцы `LowCardinality` в обычные столбцы для запросов `SELECT`, а обычные столбцы - в столбцы `LowCardinality` для запросов `INSERT`.
В основном настройка используется для сторонних клиентов, не поддерживающих тип данных `LowCardinality`.
Допустимые значения:
- 1 — Использование `LowCardinality` не ограничено.
- 0 — Использование `LowCardinality` ограничено.
Значение по умолчанию: 1.
## allow\_suspicious\_low\_cardinality\_types {#allow_suspicious_low_cardinality_types}
Разрешает или запрещает использование типа данных `LowCardinality` с типами данных с фиксированным размером 8 байт или меньше: числовые типы данных и `FixedString (8_bytes_or_less)`.
Для небольших фиксированных значений использование `LowCardinality` обычно неэффективно, поскольку ClickHouse хранит числовой индекс для каждой строки. В результате:
- Используется больше дискового пространства.
- Потребление ОЗУ увеличивается, в зависимости от размера словаря.
- Некоторые функции работают медленнее из-за дополнительных операций кодирования.
Время слияния в таблицах на движке [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md) также может увеличиться по описанным выше причинам.
Допустимые значения:
- 1 — Использование `LowCardinality` не ограничено.
- 0 — Использование `LowCardinality` ограничено.
Значение по умолчанию: 0.
## background_buffer_flush_schedule_pool_size {#background_buffer_flush_schedule_pool_size}
Задает количество потоков для выполнения фонового сброса данных в таблицах с движком [Buffer](../../engines/table-engines/special/buffer.md). Настройка применяется при запуске сервера ClickHouse и не может быть изменена в пользовательском сеансе.

View File

@ -9,7 +9,7 @@
- `volume_priority` ([UInt64](../../sql-reference/data-types/int-uint.md)) — порядковый номер тома согласно конфигурации.
- `disks` ([Array(String)](../../sql-reference/data-types/array.md)) — имена дисков, содержащихся в политике хранения.
- `max_data_part_size` ([UInt64](../../sql-reference/data-types/int-uint.md)) — максимальный размер куска данных, который может храниться на дисках тома (0 — без ограничений).
- `move_factor` ([Float64](../../sql-reference/data-types/float.md))\` — доля свободного места, при превышении которой данные начинают перемещаться на следующий том.
- `move_factor` — доля доступного свободного места на томе, если места становится меньше, то данные начнут перемещение на следующий том, если он есть (по умолчанию 0.1).
Если политика хранения содержит несколько томов, то каждому тому соответствует отдельная запись в таблице.

View File

@ -24,13 +24,16 @@
- [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md#table_engine-mergetree-multiple-volumes)
- [Distributed](../../engines/table-engines/special/distributed.md#distributed)
- `total_rows` (Nullable(UInt64)) - Общее количество строк, если есть возможность быстро определить точное количество строк в таблице, в противном случае `Null` (включая базовую таблицу `Buffer`).
- `total_rows` (Nullable(UInt64)) - общее количество строк, если есть возможность быстро определить точное количество строк в таблице, в противном случае `Null` (включая базовую таблицу `Buffer`).
- `total_bytes` (Nullable(UInt64)) - Общее количество байт, если можно быстро определить точное количество байт для таблицы на накопителе, в противном случае `Null` (**не включает** в себя никакого базового хранилища).
- `total_bytes` (Nullable(UInt64)) - общее количество байт, если можно быстро определить точное количество байт для таблицы на накопителе, в противном случае `Null` (**не включает** в себя никакого базового хранилища).
- Если таблица хранит данные на диске, возвращает используемое пространство на диске (т. е. сжатое).
- Если таблица хранит данные в памяти, возвращает приблизительное количество используемых байт в памяти.
- `lifetime_rows` (Nullable(UInt64)) - общее количество строк, добавленных оператором `INSERT` с момента запуска сервера (только для таблиц `Buffer`).
- `lifetime_bytes` (Nullable(UInt64)) - общее количество байт, добавленных оператором `INSERT` с момента запуска сервера (только для таблиц `Buffer`).
Таблица `system.tables` используется при выполнении запроса `SHOW TABLES`.

View File

@ -4,7 +4,7 @@ toc_priority: 128
# groupBitmap {#groupbitmap}
Bitmap или агрегатные вычисления для столбца с типом данных `UInt*`, возвращают кардинальность в виде значения типа UInt64, если добавить суффикс -State, то возвращают [объект bitmap](../../../sql-reference/functions/bitmap-functions.md).
Bitmap или агрегатные вычисления для столбца с типом данных `UInt*`, возвращают кардинальность в виде значения типа UInt64, если добавить суффикс `-State`, то возвращают [объект bitmap](../../../sql-reference/functions/bitmap-functions.md#bitmap-functions).
``` sql
groupBitmap(expr)

View File

@ -1,3 +1,8 @@
---
toc_priority: 53
toc_title: AggregateFunction
---
# AggregateFunction {#data-type-aggregatefunction}
Агрегатные функции могут обладать определяемым реализацией промежуточным состоянием, которое может быть сериализовано в тип данных, соответствующий AggregateFunction(…), и быть записано в таблицу обычно посредством [материализованного представления] (../../sql-reference/statements/create.md#create-view). Чтобы получить промежуточное состояние, обычно используются агрегатные функции с суффиксом `-State`. Чтобы в дальнейшем получить агрегированные данные необходимо использовать те же агрегатные функции с суффиксом `-Merge`.

View File

@ -1,3 +1,8 @@
---
toc_priority: 52
toc_title: Array(T)
---
# Array(T) {#data-type-array}
Массив из элементов типа `T`.

View File

@ -0,0 +1,59 @@
---
toc_priority: 51
toc_title: LowCardinality
---
# LowCardinality {#lowcardinality-data-type}
Изменяет внутреннее представление других типов данных, превращая их в тип со словарным кодированием.
## Синтаксис {#lowcardinality-syntax}
```sql
LowCardinality(data_type)
```
**Параметры**
- `data_type` — [String](string.md), [FixedString](fixedstring.md), [Date](date.md), [DateTime](datetime.md) и числа за исключением типа [Decimal](decimal.md). `LowCardinality` неэффективен для некоторых типов данных, см. описание настройки [allow_suspicious_low_cardinality_types](../../operations/settings/settings.md#allow_suspicious_low_cardinality_types).
## Описание {#lowcardinality-dscr}
`LowCardinality` — это надстройка, изменяющая способ хранения и правила обработки данных. ClickHouse применяет [словарное кодирование](https://en.wikipedia.org/wiki/Dictionary_coder) в столбцы типа `LowCardinality`. Работа с данными, представленными в словарном виде, может значительно увеличивать производительность запросов [SELECT](../statements/select/index.md) для многих приложений.
Эффективность использования типа данных `LowCarditality` зависит от разнообразия данных. Если словарь содержит менее 10 000 различных значений, ClickHouse в основном показывает более высокую эффективность чтения и хранения данных. Если же словарь содержит более 100 000 различных значений, ClickHouse может работать хуже, чем при использовании обычных типов данных.
При работе со строками, использование `LowCardinality` вместо [Enum](enum.md). `LowCardinality` обеспечивает большую гибкость в использовании и часто показывает такую же или более высокую эффективность.
## Пример
Создать таблицу со столбцами типа `LowCardinality`:
```sql
CREATE TABLE lc_t
(
`id` UInt16,
`strings` LowCardinality(String)
)
ENGINE = MergeTree()
ORDER BY id
```
## Связанные настройки и функции
Настройки:
- [low_cardinality_max_dictionary_size](../../operations/settings/settings.md#low_cardinality_max_dictionary_size)
- [low_cardinality_use_single_dictionary_for_part](../../operations/settings/settings.md#low_cardinality_use_single_dictionary_for_part)
- [low_cardinality_allow_in_native_format](../../operations/settings/settings.md#low_cardinality_allow_in_native_format)
- [allow_suspicious_low_cardinality_types](../../operations/settings/settings.md#allow_suspicious_low_cardinality_types)
Функции:
- [toLowCardinality](../functions/type-conversion-functions.md#tolowcardinality)
## Смотрите также
- [A Magical Mystery Tour of the LowCardinality Data Type](https://www.altinity.com/blog/2019/3/27/low-cardinality).
- [Reducing Clickhouse Storage Cost with the Low Cardinality Type Lessons from an Instana Engineer](https://www.instana.com/blog/reducing-clickhouse-storage-cost-with-the-low-cardinality-type-lessons-from-an-instana-engineer/).
- [String Optimization (video presentation in Russian)](https://youtu.be/rqf-ILRgBdY?list=PL0Z2YDlm0b3iwXCpEFiOOYmwXzVmjJfEt). [Slides in English](https://github.com/yandex/clickhouse-presentations/raw/master/meetup19/string_optimization.pdf).

View File

@ -1,3 +1,8 @@
---
toc_priority: 55
toc_title: Nullable
---
# Nullable(TypeName) {#data_type-nullable}
Позволяет работать как со значением типа `TypeName` так и с отсутствием этого значения ([NULL](../../sql-reference/data-types/nullable.md)) в одной и той же переменной, в том числе хранить `NULL` в таблицах вместе со значения типа `TypeName`. Например, в столбце типа `Nullable(Int8)` можно хранить значения типа `Int8`, а в тех строках, где значения нет, будет храниться `NULL`.

View File

@ -1,3 +1,8 @@
---
toc_priority: 54
toc_title: Tuple(T1, T2, ...)
---
# Tuple(T1, T2, …) {#tuplet1-t2}
Кортеж из элементов любого [типа](index.md#data_types). Элементы кортежа могут быть одного или разных типов.

View File

@ -1,4 +1,4 @@
# Функции для битмапов {#funktsii-dlia-bitmapov}
# Функции для битмапов {#bitmap-functions}
## bitmapBuild {#bitmap_functions-bitmapbuild}
@ -61,8 +61,8 @@ bitmapSubsetLimit(bitmap, range_start, cardinality_limit)
**Параметры**
- `bitmap` Битмап. [Bitmap object](#bitmap_functions-bitmapbuild).
- `range_start` Начальная точка подмножества. [UInt32](../../sql-reference/functions/bitmap-functions.md).
- `cardinality_limit` Верхний предел подмножества. [UInt32](../../sql-reference/functions/bitmap-functions.md).
- `range_start` Начальная точка подмножества. [UInt32](../../sql-reference/functions/bitmap-functions.md#bitmap-functions).
- `cardinality_limit` Верхний предел подмножества. [UInt32](../../sql-reference/functions/bitmap-functions.md#bitmap-functions).
**Возвращаемое значение**
@ -97,7 +97,7 @@ bitmapContains(haystack, needle)
**Параметры**
- `haystack` [объект Bitmap](#bitmap_functions-bitmapbuild), в котором функция ищет значение.
- `needle` значение, которое функция ищет. Тип — [UInt32](../../sql-reference/functions/bitmap-functions.md).
- `needle` значение, которое функция ищет. Тип — [UInt32](../../sql-reference/functions/bitmap-functions.md#bitmap-functions).
**Возвращаемые значения**

View File

@ -100,5 +100,6 @@ FROM numbers(3)
│ a*cjab+ │
│ aeca2A │
└───────────────────────────────────────┘
```
[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/random_functions/) <!--hide-->

View File

@ -508,7 +508,7 @@ SELECT parseDateTimeBestEffort('10 20:19')
**См. также**
- \[Информация о формате ISO 8601 от @xkcd\](https://xkcd.com/1179/)
- [Информация о формате ISO 8601 от @xkcd](https://xkcd.com/1179/)
- [RFC 1123](https://tools.ietf.org/html/rfc1123)
- [toDate](#todate)
- [toDateTime](#todatetime)
@ -678,4 +678,43 @@ SELECT fromUnixTimestamp64Milli(i64, 'UTC')
└──────────────────────────────────────┘
```
## toLowCardinality {#tolowcardinality}
Преобразует входные данные в версию [LowCardianlity](../data-types/lowcardinality.md) того же типа данных.
Чтобы преобразовать данные из типа `LowCardinality`, используйте функцию [CAST](#type_conversion_function-cast). Например, `CAST(x as String)`.
**Синтаксис**
```sql
toLowCardinality(expr)
```
**Параметры**
- `expr` — [Выражение](../syntax.md#syntax-expressions), которое в результате преобразуется в один из [поддерживаемых типов данных](../data-types/index.md#data_types).
**Возвращаемое значение**
- Результат преобразования `expr`.
Тип: `LowCardinality(expr_result_type)`
**Example**
Запрос:
```sql
SELECT toLowCardinality('1')
```
Результат:
```text
┌─toLowCardinality('1')─┐
│ 1 │
└───────────────────────┘
```
[Оригинальная статья](https://clickhouse.tech/docs/ru/query_language/functions/type_conversion_functions/) <!--hide-->

View File

@ -3,4 +3,28 @@ toc_folder_title: "\u0412\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F"
toc_priority: 31
---
# SQL выражения в ClickHouse {#clickhouse-sql-statements}
Выражения описывают различные действия, которые можно выполнить с помощью SQL запросов. Каждый вид выражения имеет свой синтаксис и особенности использования, которые описаны в соответствующих разделах документации:
- [SELECT](../../sql-reference/statements/select/index.md)
- [INSERT INTO](../../sql-reference/statements/insert-into.md)
- [CREATE](../../sql-reference/statements/create/index.md)
- [ALTER](../../sql-reference/statements/alter/index.md)
- [SYSTEM](../../sql-reference/statements/system.md)
- [SHOW](../../sql-reference/statements/show.md)
- [GRANT](../../sql-reference/statements/grant.md)
- [REVOKE](../../sql-reference/statements/revoke.md)
- [ATTACH](../../sql-reference/statements/attach.md)
- [CHECK TABLE](../../sql-reference/statements/check-table.md)
- [DESCRIBE TABLE](../../sql-reference/statements/describe-table.md)
- [DETACH](../../sql-reference/statements/detach.md)
- [DROP](../../sql-reference/statements/drop.md)
- [EXISTS](../../sql-reference/statements/exists.md)
- [KILL](../../sql-reference/statements/kill.md)
- [OPTIMIZE](../../sql-reference/statements/optimize.md)
- [RENAME](../../sql-reference/statements/rename.md)
- [SET](../../sql-reference/statements/set.md)
- [SET ROLE](../../sql-reference/statements/set-role.md)
- [TRUNCATE](../../sql-reference/statements/truncate.md)
- [USE](../../sql-reference/statements/use.md)

View File

@ -92,7 +92,7 @@ def test_single_page(input_path, lang):
logging.warning('Found %d duplicate anchor points' % duplicate_anchor_points)
if links_to_nowhere:
if lang == 'en': # TODO: check all languages again
if lang == 'en' or lang == 'ru': # TODO: check all languages again
logging.error(f'Found {links_to_nowhere} links to nowhere in {lang}')
sys.exit(1)
else:

View File

@ -629,6 +629,7 @@ int Server::main(const std::vector<std::string> & /*args*/)
/// Check sanity of MergeTreeSettings on server startup
global_context->getMergeTreeSettings().sanityCheck(settings);
global_context->getReplicatedMergeTreeSettings().sanityCheck(settings);
/// Limit on total memory usage
size_t max_server_memory_usage = config().getUInt64("max_server_memory_usage", 0);

View File

@ -19,12 +19,12 @@ struct ConstSource;
using NumericArraySources = typename TypeListMap<NumericArraySource, TypeListNumbersAndUInt128>::Type;
using BasicArraySources = typename AppendToTypeList<GenericArraySource, NumericArraySources>::Type;
using NullableArraySources = typename TypeListMap<NullableArraySource, BasicArraySources>::Type;
using BasicAndNullableArraySources = typename TypeListConcat<BasicArraySources, NullableArraySources>::Type;
using ConstArraySources = typename TypeListMap<ConstSource, BasicAndNullableArraySources>::Type;
using TypeListArraySources = typename TypeListConcat<BasicAndNullableArraySources, ConstArraySources>::Type;
//using NullableArraySources = typename TypeListMap<NullableArraySource, BasicArraySources>::Type;
//using BasicAndNullableArraySources = typename TypeListConcat<BasicArraySources, NullableArraySources>::Type;
//using ConstArraySources = typename TypeListMap<ConstSource, BasicAndNullableArraySources>::Type;
//using TypeListArraySources = typename TypeListConcat<BasicAndNullableArraySources, ConstArraySources>::Type;
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, TypeListArraySources>::Type
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, BasicArraySources>::Type
{
protected:
~ArraySourceVisitor() = default;

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IArraySink
{
@ -25,6 +24,8 @@ struct IArraySink
}
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ArraySinkImpl : public Visitable<Derived, IArraySink, ArraySinkVisitor> {};

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IArraySource
{
@ -31,6 +30,8 @@ struct IArraySource
}
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ArraySourceImpl : public Visitable<Derived, IArraySource, ArraySourceVisitor> {};

View File

@ -13,7 +13,6 @@ namespace ErrorCodes
namespace GatherUtils
{
#pragma GCC visibility push(hidden)
struct IValueSource
{
@ -27,6 +26,8 @@ struct IValueSource
virtual bool isConst() const { return false; }
};
#pragma GCC visibility push(hidden)
template <typename Derived>
class ValueSourceImpl : public Visitable<Derived, IValueSource, ValueSourceVisitor> {};

View File

@ -32,20 +32,30 @@ void callSelectMemberFunctionWithTupleArgument(Tuple & tuple, Args && ... args)
callSelectMemberFunctionWithTupleArgument<Base, Tuple, index + 1>(tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename Tuple, int index, typename ... Args>
void callSelectSource(bool is_const, bool is_nullable, Tuple & tuple, Args && ... args)
{
if constexpr (index == std::tuple_size<Tuple>::value)
Base::selectSource(is_const, is_nullable, args ...);
else
callSelectSource<Base, Tuple, index + 1>(is_const, is_nullable, tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename ... Args>
struct ArraySourceSelectorVisitor final : public ArraySourceVisitorImpl<ArraySourceSelectorVisitor<Base, Args ...>>
{
explicit ArraySourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
explicit ArraySourceSelectorVisitor(IArraySource & source, Args && ... args) : packed_args(args ...), array_source(source) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
callSelectSource<Base, Tuple, 0>(array_source.isConst(), array_source.isNullable(), packed_args, source);
}
Tuple packed_args;
IArraySource & array_source;
};
template <typename Base>
@ -54,7 +64,7 @@ struct ArraySourceSelector
template <typename ... Args>
static void select(IArraySource & source, Args && ... args)
{
ArraySourceSelectorVisitor<Base, Args ...> visitor(args ...);
ArraySourceSelectorVisitor<Base, Args ...> visitor(source, args ...);
source.accept(visitor);
}
};
@ -87,56 +97,6 @@ struct ArraySinkSelector
}
};
template <typename Base, typename ... Args>
struct ValueSourceSelectorVisitor final : public ValueSourceVisitorImpl<ValueSourceSelectorVisitor<Base, Args ...>>
{
explicit ValueSourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
}
Tuple packed_args;
};
template <typename Base>
struct ValueSourceSelector
{
template <typename ... Args>
static void select(IValueSource & source, Args && ... args)
{
ValueSourceSelectorVisitor<Base, Args ...> visitor(args ...);
source.accept(visitor);
}
};
template <typename Base>
struct ArraySinkSourceSelector
{
template <typename ... Args>
static void select(IArraySource & source, IArraySink & sink, Args && ... args)
{
ArraySinkSelector<Base>::select(sink, source, args ...);
}
template <typename Sink, typename ... Args>
static void selectImpl(Sink && sink, IArraySource & source, Args && ... args)
{
ArraySourceSelector<Base>::select(source, sink, args ...);
}
template <typename Source, typename Sink, typename ... Args>
static void selectImpl(Source && source, Sink && sink, Args && ... args)
{
Base::selectSourceSink(source, sink, args ...);
}
};
template <typename Base>
struct ArraySourcePairSelector
{
@ -147,15 +107,17 @@ struct ArraySourcePairSelector
}
template <typename FirstSource, typename ... Args>
static void selectImpl(FirstSource && first, IArraySource & second, Args && ... args)
static void selectSource(bool is_const, bool is_nullable, FirstSource && first, IArraySource & second, Args && ... args)
{
ArraySourceSelector<Base>::select(second, first, args ...);
ArraySourceSelector<Base>::select(second, is_const, is_nullable, first, args ...);
}
template <typename SecondSource, typename FirstSource, typename ... Args>
static void selectImpl(SecondSource && second, FirstSource && first, Args && ... args)
static void selectSource(bool is_second_const, bool is_second_nullable, SecondSource && second,
bool is_first_const, bool is_first_nullable, FirstSource && first, Args && ... args)
{
Base::selectSourcePair(first, second, args ...);
Base::selectSourcePair(is_first_const, is_first_nullable, first,
is_second_const, is_second_nullable, second, args ...);
}
};

View File

@ -23,37 +23,54 @@ struct ArrayConcat : public ArraySourceSelector<ArrayConcat>
{
using Sources = std::vector<std::unique_ptr<IArraySource>>;
// template <typename Source>
// static void selectSource(Source && source, const Sources & sources, ColumnArray::MutablePtr & result)
// {
// using SourceType = typename std::decay<Source>::type;
// using Sink = typename SourceType::SinkType;
// result = ColumnArray::create(source.createValuesColumn());
// Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
//
// concat<SourceType, Sink>(sources, std::move(sink));
// }
//
// template <typename Source>
// static void selectImpl(ConstSource<Source> && source, const Sources & sources, ColumnArray::MutablePtr & result)
// {
// using SourceType = typename std::decay<Source>::type;
// using Sink = typename SourceType::SinkType;
// result = ColumnArray::create(source.createValuesColumn());
// Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
//
// concat<SourceType, Sink>(sources, std::move(sink));
// }
template <typename Source>
static void selectImpl(Source && source, const Sources & sources, ColumnArray::MutablePtr & result)
static void selectSource(bool /*is_const*/, bool is_nullable, Source & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
template <typename Source>
static void selectImpl(ConstSource<Source> && source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
auto & nullable_source = static_cast<NullableSource &>(source);
concat<SourceType, Sink>(sources, std::move(sink));
}
template <typename Source>
static void selectImpl(ConstSource<Source> & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
concat<NullableSource, NullableSink>(sources, std::move(sink));
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAllSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAllSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::All>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAnySelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAnySelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Any>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasSubstrSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasSubstrSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Substr>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -13,13 +13,37 @@ namespace
struct SliceDynamicOffsetBoundedSelectArraySource : public ArraySourceSelector<SliceDynamicOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source,
const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(static_cast<NullableSource &>(source), sink, offset_column, length_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceDynamicOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceDynamicOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetUnbounded(source, sink, offset_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(source, sink, offset_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
}
}
};

View File

@ -355,6 +355,7 @@ struct ContextShared
mutable std::shared_ptr<const StoragePolicySelector> merge_tree_storage_policy_selector;
std::optional<MergeTreeSettings> merge_tree_settings; /// Settings of MergeTree* engines.
std::optional<MergeTreeSettings> replicated_merge_tree_settings; /// Settings of ReplicatedMergeTree* engines.
std::atomic_size_t max_table_size_to_drop = 50000000000lu; /// Protects MergeTree tables from accidental DROP (50GB by default)
std::atomic_size_t max_partition_size_to_drop = 50000000000lu; /// Protects MergeTree partitions from accidental DROP (50GB by default)
String format_schema_path; /// Path to a directory that contains schema files used by input formats.
@ -1887,6 +1888,22 @@ const MergeTreeSettings & Context::getMergeTreeSettings() const
return *shared->merge_tree_settings;
}
const MergeTreeSettings & Context::getReplicatedMergeTreeSettings() const
{
auto lock = getLock();
if (!shared->replicated_merge_tree_settings)
{
const auto & config = getConfigRef();
MergeTreeSettings mt_settings;
mt_settings.loadFromConfig("merge_tree", config);
mt_settings.loadFromConfig("replicated_merge_tree", config);
shared->replicated_merge_tree_settings.emplace(mt_settings);
}
return *shared->replicated_merge_tree_settings;
}
const StorageS3Settings & Context::getStorageS3Settings() const
{
#if !defined(ARCADIA_BUILD)

View File

@ -545,6 +545,7 @@ public:
std::shared_ptr<PartLog> getPartLog(const String & part_database);
const MergeTreeSettings & getMergeTreeSettings() const;
const MergeTreeSettings & getReplicatedMergeTreeSettings() const;
const StorageS3Settings & getStorageS3Settings() const;
/// Prevents DROP TABLE if its size is greater than max_size (50GB by default, max_size=0 turn off this check)

View File

@ -33,7 +33,7 @@ void ReplicasStatusHandler::handleRequest(Poco::Net::HTTPServerRequest & request
/// Even if lag is small, output detailed information about the lag.
bool verbose = params.get("verbose", "") == "1";
const MergeTreeSettings & settings = context.getMergeTreeSettings();
const MergeTreeSettings & settings = context.getReplicatedMergeTreeSettings();
bool ok = true;
std::stringstream message;

View File

@ -535,7 +535,11 @@ static StoragePtr create(const StorageFactory::Arguments & args)
StorageInMemoryMetadata metadata;
metadata.columns = args.columns;
std::unique_ptr<MergeTreeSettings> storage_settings = std::make_unique<MergeTreeSettings>(args.context.getMergeTreeSettings());
std::unique_ptr<MergeTreeSettings> storage_settings;
if (replicated)
storage_settings = std::make_unique<MergeTreeSettings>(args.context.getReplicatedMergeTreeSettings());
else
storage_settings = std::make_unique<MergeTreeSettings>(args.context.getMergeTreeSettings());
if (is_extended_storage_def)
{

View File

@ -7,7 +7,8 @@
namespace DB
{
NamesAndTypesList SystemMergeTreeSettings::getNamesAndTypes()
template <bool replicated>
NamesAndTypesList SystemMergeTreeSettings<replicated>::getNamesAndTypes()
{
return {
{"name", std::make_shared<DataTypeString>()},
@ -18,9 +19,11 @@ NamesAndTypesList SystemMergeTreeSettings::getNamesAndTypes()
};
}
void SystemMergeTreeSettings::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const
template <bool replicated>
void SystemMergeTreeSettings<replicated>::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const
{
for (const auto & setting : context.getMergeTreeSettings().all())
const auto & settings = replicated ? context.getReplicatedMergeTreeSettings().all() : context.getMergeTreeSettings().all();
for (const auto & setting : settings)
{
res_columns[0]->insert(setting.getName());
res_columns[1]->insert(setting.getValueString());
@ -30,4 +33,6 @@ void SystemMergeTreeSettings::fillData(MutableColumns & res_columns, const Conte
}
}
template class SystemMergeTreeSettings<false>;
template class SystemMergeTreeSettings<true>;
}

View File

@ -11,18 +11,22 @@ namespace DB
class Context;
/** implements system table "merge_tree_settings", which allows to get information about the current MergeTree settings.
/** implements system table "merge_tree_settings" and "replicated_merge_tree_settings",
* which allows to get information about the current MergeTree settings.
*/
class SystemMergeTreeSettings final : public ext::shared_ptr_helper<SystemMergeTreeSettings>, public IStorageSystemOneBlock<SystemMergeTreeSettings>
template <bool replicated>
class SystemMergeTreeSettings final : public ext::shared_ptr_helper<SystemMergeTreeSettings<replicated>>,
public IStorageSystemOneBlock<SystemMergeTreeSettings<replicated>>
{
friend struct ext::shared_ptr_helper<SystemMergeTreeSettings>;
friend struct ext::shared_ptr_helper<SystemMergeTreeSettings<replicated>>;
public:
std::string getName() const override { return "SystemMergeTreeSettings"; }
std::string getName() const override { return replicated ? "SystemReplicatedMergeTreeSettings" : "SystemMergeTreeSettings"; }
static NamesAndTypesList getNamesAndTypes();
protected:
using IStorageSystemOneBlock::IStorageSystemOneBlock;
using IStorageSystemOneBlock<SystemMergeTreeSettings<replicated>>::IStorageSystemOneBlock;
void fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo & query_info) const override;
};

View File

@ -82,7 +82,8 @@ void attachSystemTablesLocal(IDatabase & system_database)
attach<StorageSystemFunctions>(system_database, "functions");
attach<StorageSystemEvents>(system_database, "events");
attach<StorageSystemSettings>(system_database, "settings");
attach<SystemMergeTreeSettings>(system_database, "merge_tree_settings");
attach<SystemMergeTreeSettings<false>>(system_database, "merge_tree_settings");
attach<SystemMergeTreeSettings<true>>(system_database, "replicated_merge_tree_settings");
attach<StorageSystemBuildOptions>(system_database, "build_options");
attach<StorageSystemFormats>(system_database, "formats");
attach<StorageSystemTableFunctions>(system_database, "table_functions");

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<yandex>
<merge_tree>
<index_granularity>100</index_granularity>
</merge_tree>
<replicated_merge_tree>
<index_granularity>200</index_granularity>
</replicated_merge_tree>
</yandex>

View File

@ -0,0 +1,36 @@
import pytest
from helpers.cluster import ClickHouseCluster
import logging
cluster = ClickHouseCluster(__file__)
node = cluster.add_instance("node", main_configs=["configs/config.xml"], with_zookeeper=True)
@pytest.fixture(scope="module")
def start_cluster():
try:
logging.info("Starting cluster...")
cluster.start()
logging.info("Cluster started")
yield cluster
finally:
cluster.shutdown()
@pytest.fixture(autouse=True)
def drop_table(start_cluster):
yield
for node in cluster.instances.values():
node.query("DROP TABLE IF EXISTS test1")
node.query("DROP TABLE IF EXISTS test2")
def test_replicated_merge_tree_settings(start_cluster):
node.query("CREATE TABLE test1 (id Int64) ENGINE MergeTree ORDER BY id")
node.query(
"CREATE TABLE test2 (id Int64) ENGINE ReplicatedMergeTree('/clickhouse/test', 'test') ORDER BY id"
)
assert "index_granularity = 100" in node.query("SHOW CREATE test1")
assert "index_granularity = 200" in node.query("SHOW CREATE test2")