Важно: Данный раздел актуален для Платформы данных On-Premise.
Наименование системы: RT.WideStore.
RT.WideStore – столбцовая система управления базами данных, предназначенная для онлайн обработки аналитических запросов (OLAP).
В настоящем документе использованы и определены следующие термины и сокращения:
Термин/ Сокращение |
Определение |
---|---|
OLAP | (англ. online analytical processing, интерактивная аналитическая обработка) – технология обработки данных, заключающаяся в подготовке суммарной (агрегированной) информации на основе больших массивов данных, структурированных по многомерному принципу. |
SQL | (англ. structured query language, язык структурированных запросов) –декларативный язык программирования, применяемый для создания, модификации и управления данными в реляционной базе данных, управляемой соответствующей системой управления базами данных. |
БД | База данных |
ОС | Операционная система |
Система | Система «RT.WideStore» |
СУБД | Система управлением базами данных |
HTTP | (англ. HyperText Transfer Protocol – «протокол передачи гипертекста») – протокол прикладного уровня передачи данных, изначально – в виде гипертекстовых документов в формате HTML, в настоящее время используется для передачи произвольных данных. |
TCP | (англ. Transmission Control Protocol – протокол управления передачей) – один из основных протоколов передачи данных интернета, предназначенный для управления передачей данных интернета. Пакеты в TCP называются сегментами. |
MySQL | Свободная реляционная система управления базами данных. Разработку и поддержку MySQL осуществляет корпорация Oracle, получившая права на торговую марку вместе с поглощённой Sun Microsystems, которая ранее приобрела шведскую компанию MySQL AB. |
MySQL CLI | Консольный клиент MySQL для работы с базами данных. |
URL | (от англ. Uniform Resource Locator – Унифицированный указатель ресурса) – система унифицированных адресов электронных ресурсов, или единообразный определитель местонахождения ресурса (файла). Используется как стандарт записи ссылок на объекты в Интернете. |
Re2 | Библиотека регулярных выражений. |
СУБД RT.WideStore из-за своей архитектуры оптимальна для выполнения онлайн запросов используемых для построения отчетов на основе больших массивов данных, структурированных по многомерному принципу.
Пользователи Системы должен иметь навыки работы со следующими продуктами:
Администратор должен обладать необходимыми и достаточными доступами, в том числе сетевыми, к предустановленным в рамках Системы компонентам.
Для получения паролей к учетным записям для проведения работ на системе администратору необходимо обращаться в подразделение, осуществляющее поддержку соответствующих систем (RT.WideStore).
Первичная проверка работоспособности компонентов системы заключается в контроле получения доступа к схемам СУБД RT.WideStore, в том числе тестовым, где установлены компоненты Системы.
Для выполнения работы с СУБД RT.WideStore необходимо рассмотреть следующие разделы:
Возможные подключения к СУБД RT.WideStore описаны в документе «RT.WideStore. Общее описание системы» в разделе 5.18 «Интерфейсы взаимодействия с Системой».
Более подробно разберем следующие варианты подключения:
RT.WideStore предоставляет собственный клиент командной строки: clickhouse-client. Клиент поддерживает запуск с аргументами командной строки и с конфигурационными файлами. Подробнее читайте в разделе Конфигурирование.
Клиент устанавливается пакетом clickhouse-client и запускается командой clickhouse-client.
$ clickhouse-client
ClickHouse client version 20.13.1.5273 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.13.1 revision 54442.
:)
Клиенты и серверы различных версий совместимы, однако если клиент старее сервера, то некоторые новые функции могут быть недоступны. Мы рекомендуем использовать одинаковые версии клиента и сервера. При подключении клиента к более новому серверу clickhouse-client выводит сообщение:
ClickHouse client version is older than ClickHouse server. It may lack support for new features.
Клиент может быть использован в интерактивном и не интерактивном (batch) режиме.
Чтобы использовать batch режим, укажите параметр query, или отправьте данные в stdin (проверяется, что stdin - не терминал), или и то, и другое.
Аналогично HTTP интерфейсу, при использовании одновременно параметра query и отправке данных в stdin, запрос составляется из конкатенации параметра query, перевода строки, и данных в stdin. Это удобно для больших INSERT запросов.
Примеры использования клиента для вставки данных:
$ echo -ne "1, 'some text', '2016-08-14 00:00:00'\n2, 'some more text', '2016-08-14 00:00:01'" | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
$ cat <<_EOF | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
3, 'some text', '2016-08-14 00:00:00'
4, 'some more text', '2016-08-14 00:00:01'
_EOF
$ cat file.csv | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
В batch режиме в качестве формата данных по умолчанию используется формат TabSeparated. Формат может быть указан в секции FORMAT запроса.
По умолчанию, в batch режиме вы можете выполнить только один запрос. Чтобы выполнить несколько запросов из «скрипта», используйте параметр –multiquery. Это работает для всех запросов кроме INSERT. Результаты запросов выводятся подряд без дополнительных разделителей.
Также, при необходимости выполнить много запросов, вы можете запускать clickhouse-client на каждый запрос. Заметим, что запуск программы clickhouse-client может занимать десятки миллисекунд.
В интерактивном режиме, вы получите командную строку, в которую можно вводить запросы.
Если не указано multiline (по умолчанию):
Если указано multiline (многострочный режим):
Исполняется только один запрос, поэтому всё, что введено после точки с запятой, игнорируется.
Вместо или после точки с запятой может быть указано \G. Это обозначает использование формата Vertical. В этом формате каждое значение выводится на отдельной строке, что удобно для широких таблиц. Столь необычная функциональность добавлена для совместимости с MySQL CLI.
Командная строка сделана на основе readline (и history) (или libedit, или без какой-либо библиотеки, в зависимости от сборки) - то есть, в ней работают привычные сочетания клавиш, а также присутствует история.
История пишется в ~/.clickhouse-client-history.
По умолчанию, в качестве формата, используется формат PrettyCompact (красивые таблички). Вы можете изменить формат с помощью секции FORMAT запроса, или с помощью указания \G на конце запроса, с помощью аргумента командной строки --format или --vertical, или с помощью конфигурационного файла клиента.
Чтобы выйти из клиента, нажмите Ctrl+D, или наберите вместо запроса одно из: «exit», «quit», «logout», «учше», «йгше», «дщпщге», «exit;», «quit;», «logout;», «учшеж», «йгшеж», «дщпщгеж», «q», «й», «q», «Q», «:q», «й», «Й», «Жй»
При выполнении запроса, клиент показывает:
Вы можете прервать длинный запрос, нажав Ctrl+C. При этом вам всё равно придётся чуть-чуть подождать, пока сервер остановит запрос. На некоторых стадиях выполнения, запрос невозможно прервать. Если вы не дождётесь и нажмёте Ctrl+C второй раз, то клиент будет завершён.
Клиент командной строки позволяет передать внешние данные (внешние временные таблицы) для использования запроса. Подробнее смотрите раздел «Внешние данные для обработки запроса».
Вы можете создать запрос с параметрами и передавать в них значения из приложения. Это позволяет избежать форматирования запросов на стороне клиента, если известно, какие из параметров запроса динамически меняются. Например:
clickhouse-client --param_parName="[1, 2]" -q "SELECT * FROM table WHERE a = {parName:Array(UInt16)}"
Cинтаксис запроса:
Отформатируйте запрос обычным способом. Представьте значения, которые вы хотите передать из параметров приложения в запрос в следующем формате:
{<name>:<data type>}
Где:
Пример:
$ clickhouse-client --param_tuple_in_tuple="(10, ('dt', 10))" -q "SELECT * FROM table WHERE val = {tuple_in_tuple:Tuple(UInt8, Tuple(String, UInt8))}"
$ clickhouse-client --param_tbl="numbers" --param_db="system" --param_col="number" --query "SELECT {col:Identifier} FROM {db:Identifier}.{tbl:Identifier} LIMIT 10"
В clickhouse-client можно передавать различные параметры (все параметры имеют значения по умолчанию) с помощью:
Параметры командной строки переопределяют значения по умолчанию и параметры конфигурационных файлов.
Параметры в конфигурационных файлах переопределяют значения по умолчанию.
Параметры командной строки в clickhouse-client:
Начиная с версии 20.5, в clickhouse-client есть автоматическая подсветка синтаксиса (включена всегда).
clickhouse –client использует первый существующий файл из:
Пример конфигурационного файла:
<config>
<user>username</user>
<password>password</password>
<secure>False</secure>
</config>
Нативный протокол используется в клиенте командной строки, для взаимодействия между серверами во время обработки распределенных запросов, а также в других программах на C++. К сожалению, у родного протокола RT.WideStore пока нет формальной спецификации, но в нем можно разобраться с использованием исходного кода RT.WideStore и/или путем перехвата и анализа TCP трафика.
HTTP интерфейс позволяет использовать RT.WideStore на любой платформе, из любого языка программирования. У нас он используется для работы из Java и Perl, а также из shell-скриптов. В других отделах, HTTP интерфейс используется из Perl, Python и Go. HTTP интерфейс более ограничен по сравнению с родным интерфейсом, но является более совместимым.
По умолчанию, clickhouse-server слушает HTTP на порту 8123 (это можно изменить в конфиге).
Если запросить GET / без параметров, то вернётся строка заданная с помощью настройки http_server_default_response. Значение по умолчанию «Ok.» (с переводом строки на конце).
$ curl 'http://localhost:8123/'
Ok.
В скриптах проверки доступности вы можете использовать GET /ping без параметров. Если сервер доступен всегда возвращается «Ok.» (с переводом строки на конце).
$ curl 'http://localhost:8123/ping'
Ok.
Запрос отправляется в виде URL параметра с именем query. Или как тело запроса при использовании метода POST.
Или начало запроса в URL параметре query, а продолжение POST-ом (зачем это нужно, будет объяснено ниже). Размер URL ограничен 16KB, это следует учитывать при отправке больших запросов.
В случае успеха, вам вернётся код ответа 200 и результат обработки запроса в теле ответа.
В случае ошибки, вам вернётся код ответа 500 и текст с описанием ошибки в теле ответа.
При использовании метода GET, выставляется настройка readonly. То есть, для запросов, модифицирующие данные, можно использовать только метод POST. Сам запрос при этом можно отправлять как в теле POST-а, так и в параметре URL.
Примеры:
$ curl 'http://localhost:8123/?query=SELECT%201'
1
$ wget -nv -O- 'http://localhost:8123/?query=SELECT 1'
1
$ echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
HTTP/1.0 200 OK
Date: Wed, 27 Nov 2019 10:30:18 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
X-ClickHouse-Server-Display-Name: clickhouse.ru-central1.internal
X-ClickHouse-Query-Id: 5abe861c-239c-467f-b955-8a201abb8b7f
X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
1
Как видно, curl немного неудобен тем, что надо URL-эскейпить пробелы.
Хотя wget сам всё эскейпит, но его не рекомендуется использовать, так как он плохо работает по HTTP 1.1 при использовании keep-alive и Transfer-Encoding: chunked.
$ echo 'SELECT 1' | curl 'http://localhost:8123/' --data-binary @-
1
$ echo 'SELECT 1' | curl 'http://localhost:8123/?query=' --data-binary @-
1
$ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
Если часть запроса отправляется в параметре, а часть POST-ом, то между этими двумя кусками данных ставится перевод строки.
Пример (так работать не будет):
$ echo 'ECT 1' | curl 'http://localhost:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception
По умолчанию, данные возвращаются в формате TabSeparated.
Можно попросить любой другой формат - с помощью секции FORMAT запроса.
Кроме того, вы можете использовать параметр URL-адреса default_format или заголовок X-ClickHouse-Format, чтобы указать формат по умолчанию, отличный от TabSeparated.
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
┏━┓
┃1 ┃
┡━┩
│ 1 │
└───┘
Возможность передавать данные POST-ом нужна для INSERT-запросов. В этом случае вы можете написать начало запроса в параметре URL, а вставляемые данные передать POST-ом. Вставляемыми данными может быть, например, tab-separated дамп, полученный из MySQL. Таким образом, запрос INSERT заменяет LOAD DATA LOCAL INFILE из MySQL.
Примеры:
Создаём таблицу:
$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-
Используем привычный запрос INSERT для вставки данных:
$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-
Данные можно отправить отдельно от запроса:
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
Можно указать любой формат для данных. Формат Values – то же, что используется при записи INSERT INTO t VALUES:
$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-
Можно вставить данные из tab-separated дампа, указав соответствующий формат:
$ echo -ne '10\n11\n12\n' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-
Прочитаем содержимое таблицы. Данные выводятся в произвольном порядке из-за параллельной обработки запроса:
7
8
9
10
11
12
1
2
3
4
5
6
Удаляем таблицу:
$ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @-
Для запросов, которые не возвращают таблицу с данными, в случае успеха, выдаётся пустое тело ответа.
Сжатие можно использовать для уменьшения трафика по сети при передаче большого количества данных, а также для создания сразу сжатых дампов.
Вы можете использовать внутренний формат сжатия RT.WideStore при передаче данных. Формат сжатых данных нестандартный, и вам придётся использовать для работы с ним специальную программу clickhouse-compressor. Она устанавливается вместе с пакетом clickhouse-client. Для повышения эффективности вставки данных можно отключить проверку контрольной суммы на стороне сервера с помощью настройки http_native_compression_disable_checksumming_on_decompress.
Если вы указали compress=1 в URL, то сервер сжимает данные, которые он отправляет. Если вы указали decompress=1 в URL, сервер распаковывает те данные, которые вы передаёте методом POST.
Также можно использовать сжатие HTTP. RT.WideStore поддерживает следующие методы сжатия:
Для отправки сжатого запроса POST, добавьте заголовок Content-Encoding: compression_method.
Чтобы RT.WideStore сжимал ответ, разрешите сжатие настройкой enable_http_compression и добавьте заголовок Accept-Encoding: compression_method. Уровень сжатия данных для всех методов сжатия можно задать с помощью настройки http_zlib_compression_level.
Примечание: Некоторые HTTP-клиенты могут по умолчанию распаковывать данные (gzip и deflate) с сервера в фоновом режиме, и вы можете получить распакованные данные, даже если правильно используете настройки сжатия.
Примеры:
# Отправка сжатых данных на сервер
$ echo "SELECT 1" | gzip -c | \
curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/'
# Получение сжатых данных с сервера
$ curl -vsS "http://localhost:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3'
$ zcat result.gz
0
1
2
Вы можете использовать параметр URL database или заголовок X-ClickHouse-Database, чтобы указать БД по умолчанию.
$ echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
0
1
2
3
4
5
6
7
8
9
По умолчанию используется БД, которая прописана в настройках сервера, как БД по умолчанию. По умолчанию, это - БД default. Также вы всегда можете указать БД через точку перед именем таблицы.
Имя пользователя и пароль могут быть указаны в одном из трёх вариантов:
1. С использованием HTTP Basic Authentication. Пример:
$ echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
2. В параметрах URL user и password. Пример:
$ echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-
3. С использованием заголовков ‘X-ClickHouse-User’ и ‘X-ClickHouse-Key’. Пример:
$ echo 'SELECT 1' | curl -H 'X-ClickHouse-User: user' -H 'X-ClickHouse-Key: password' 'http://localhost:8123/' -d @-
Если пользователь не задан, то используется default. Если пароль не задан, то используется пустой пароль.
Также в параметрах URL вы можете указать любые настройки, которые будут использованы для обработки одного запроса, или целые профили настроек. Пример:
http://localhost:8123/?profile=web&max_rows_to_read=1000000000&query=SELECT+1
Подробнее смотрите в документе: «RT.WideStore. Инструкция администратора» п.2.10 «Настройки».
$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
0
1
2
3
4
5
6
7
8
9
Об остальных параметрах смотри раздел «SET».
Аналогично можно использовать RT.WideStore-сессии в HTTP-протоколе. Для этого необходимо добавить к запросу GET параметр session_id. В качестве идентификатора сессии можно использовать произвольную строку. По умолчанию через 60 секунд бездействия сессия будет прервана. Можно изменить этот таймаут, изменяя настройку default_session_timeout в конфигурации сервера, или добавив к запросу GET параметр session_timeout. Статус сессии можно проверить с помощью параметра session_check=1. В рамках одной сессии одновременно может исполняться только один запрос.
Прогресс выполнения запроса можно отслеживать с помощью заголовков ответа X-ClickHouse-Progress. Для этого включите send_progress_in_http_headers. Пример последовательности заголовков:
X-ClickHouse-Progress: {"read_rows":"2752512","read_bytes":"240570816","total_rows_to_read":"8880128"}
X-ClickHouse-Progress: {"read_rows":"5439488","read_bytes":"482285394","total_rows_to_read":"8880128"}
X-ClickHouse-Progress: {"read_rows":"8783786","read_bytes":"819092887","total_rows_to_read":"8880128"}
Возможные поля заголовка:
Запущенные запросы не останавливаются автоматически при разрыве HTTP соединения. Парсинг и форматирование данных производится на стороне сервера и использование сети может быть неэффективным.
Может быть передан необязательный параметр query_id - идентификатор запроса, произвольная строка. Подробнее смотрите раздел «Настройки, replace_running_query».
Может быть передан необязательный параметр quota_key - ключ квоты, произвольная строка. Подробнее смотрите раздел «Квоты».
HTTP интерфейс позволяет передать внешние данные (внешние временные таблицы) для использования запроса. Подробнее смотрите раздел «Внешние данные для обработки запроса»
Существует возможность включить буферизацию ответа на стороне сервера. Для этого предусмотрены параметры URL buffer_size и wait_end_of_query.
buffer_size определяет количество байт результата которые будут буферизованы в памяти сервера. Если тело результата больше этого порога, то буфер будет переписан в HTTP канал, а оставшиеся данные будут отправляться в HTTP-канал напрямую.
Чтобы гарантировать буферизацию всего ответа необходимо выставить wait_end_of_query=1. В этом случае данные, не поместившиеся в памяти, будут буферизованы во временном файле сервера.
Пример:
$ curl -sS
'http://localhost:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d
'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'
Буферизация позволяет избежать ситуации, когда код ответа и HTTP-заголовки были отправлены клиенту, после чего возникла ошибка выполнения запроса. В такой ситуации сообщение об ошибке записывается в конце тела ответа, и на стороне клиента ошибка может быть обнаружена только на этапе парсинга.
Можно создать запрос с параметрами и передать для них значения из соответствующих параметров HTTP-запроса. Дополнительную информацию смотрите в Запросы с параметрами для консольного клиента.
Пример:
$ curl -sS "http://localhost:8123/?param_id=2¶m_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"
RT.WideStore поддерживает определенные запросы через HTTP-интерфейс. Например, вы можете записать данные в таблицу следующим образом:
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
RT.WideStore также поддерживает предопределенный HTTP-интерфейс, который может помочь вам легче интегрироваться со сторонними инструментами, такими как Prometheus exporter.
Пример:
<http_handlers>
<rule>
<url>/predefined_query</url>
<methods>POST,GET</methods>
<handler>
<type>predefined_query_handler</type>
<query>SELECT * FROM system.metrics LIMIT 5 FORMAT Template SETTINGS format_template_resultset = 'prometheus_template_output_format_resultset', format_template_row = 'prometheus_template_output_format_row', format_template_rows_between_delimiter = '\n'</query>
</handler>
</rule>
<rule>...</rule>
<rule>...</rule>
</http_handlers>
$ curl -v 'http://localhost:8123/predefined_query'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /predefined_query HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 28 Apr 2020 08:52:56 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< X-ClickHouse-Server-Display-Name: i-mloy5trc
< Transfer-Encoding: chunked
< X-ClickHouse-Query-Id: 96fe0052-01e6-43ce-b12a-6b7370de6e8a
< X-ClickHouse-Format: Template
< X-ClickHouse-Timezone: Asia/Shanghai
< Keep-Alive: timeout=3
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
<
# HELP "Query" "Number of executing queries"
# TYPE "Query" counter
"Query" 1
# HELP "Merge" "Number of executing background merges"
# TYPE "Merge" counter
"Merge" 0
# HELP "PartMutation" "Number of mutations (ALTER DELETE/UPDATE)"
# TYPE "PartMutation" counter
"PartMutation" 0
# HELP "ReplicatedFetch" "Number of data parts being fetched from replica"
# TYPE "ReplicatedFetch" counter
"ReplicatedFetch" 0
# HELP "ReplicatedSend" "Number of data parts being sent to replicas"
# TYPE "ReplicatedSend" counter
"ReplicatedSend" 0
* Connection #0 to host localhost left intact
* Connection #0 to host localhost left intact
Как вы можете видеть из примера, http_handlers настраивается в файле config.xml и может содержать несколько правил. RT.WideStore будет сопоставлять полученные HTTP-запросы с предопределенным типом в правиле, и первое совпадение запустит обработчик. Затем RT.WideStore выполнит соответствующий предопределенный запрос.
В настоящий момент с помощью rule можно настроить method, headers, url, handler:
Далее приведены методы настройки для различных типов.
Predefined_query_handler поддерживает настройки Settings и query_params значений. Вы можете настроить запрос в типе predefined_query_handler.
Значение query – это предопределенный запрос predefined_query_handler, который выполняется RT.WideStore при совпадении HTTP-запроса и возврате результата запроса. Это обязательная настройка.
В следующем примере определяются настройки max_threads и max_alter_threads, а затем запрашивается системная таблица, чтобы проверить, были ли эти параметры успешно установлены.
Пример:
<http_handlers>
<rule>
<url><![CDATA[/query_param_with_url/\w+/(?P<name_1>[^/]+)(/(?P<name_2>[^/]+))?]]></url>
<method>GET</method>
<headers>
<XXX>TEST_HEADER_VALUE</XXX>
<PARAMS_XXX><![CDATA[(?P<name_1>[^/]+)(/(?P<name_2>[^/]+))?]]></PARAMS_XXX>
</headers>
<handler>
<type>predefined_query_handler</type>
<query>SELECT value FROM system.settings WHERE name = {name_1:String}</query>
<query>SELECT name, value FROM system.settings WHERE name = {name_2:String}</query>
</handler>
</rule>
</http_handlers>
$ curl -H 'XXX:TEST_HEADER_VALUE' -H 'PARAMS_XXX:max_threads' 'http://localhost:8123/query_param_with_url/1/max_threads/max_alter_threads?max_threads=1&max_alter_threads=2'
1
max_alter_threads 2
Предупреждение: В одном predefined_query_handler поддерживается только один запрос типа INSERT.
В Dynamic_query_handler, запрос пишется в виде параметров HTTP-запроса. Разница в том, что в predefined_query_handler, запрос записывается в конфигурационный файл. Вы можете настроить query_param_name в dynamic_query_handler.
RT.WideStore извлекает и выполняет значение, соответствующее значению query_param_name URL-адресе HTTP-запроса. Значение по умолчанию query_param_name – это /query. Это необязательная настройка. Если в файле конфигурации нет определения, параметр не передается.
Чтобы поэкспериментировать с этой функциональностью, в примере определяются значения max_threads и max_alter_threads и запрашивается, успешно ли были установлены настройки.
Пример:
<http_handlers>
<rule>
<headers>
<XXX>TEST_HEADER_VALUE_DYNAMIC</XXX> </headers>
<handler>
<type>dynamic_query_handler</type>
<query_param_name>query_param</query_param_name>
</handler>
</rule>
</http_handlers>
$ curl -H 'XXX:TEST_HEADER_VALUE_DYNAMIC' 'http://localhost:8123/own?max_threads=1&max_alter_threads=2¶m_name_1=max_threads¶m_name_2=max_alter_threads&query_param=SELECT%20name,value%20FROM%20system.settings%20where%20name%20=%20%7Bname_1:String%7D%20OR%20name%20=%20%7Bname_2:String%7D'
max_threads 1
max_alter_threads 2
Static может возвращать content_type, status и response_content. response_content может возвращать конкретное содержимое.
Пример:
Возвращает сообщение.
<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/hi</url>
<handler>
<type>static</type>
<status>402</status>
<content_type>text/html; charset=UTF-8</content_type>
<response_content>Say Hi!</response_content>
</handler>
</rule>
<http_handlers>
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/hi'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /hi HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 402 Payment Required
< Date: Wed, 29 Apr 2020 03:51:26 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=3
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
<
* Connection #0 to host localhost left intact
Say Hi!%
Находит содержимое настроек, отправленных клиенту.
<get_config_static_handler><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></get_config_static_handler>
<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_config_static_handler</url>
<handler>
<type>static</type>
<response_content>config://get_config_static_handler</response_content>
</handler>
</rule>
</http_handlers>
$ curl -v -H 'XXX:xxx' 'http://localhost:8123/get_config_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_config_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:01:24 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=3
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
<
* Connection #0 to host localhost left intact
<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>%
Находит содержимое файла, отправленного клиенту.
<http_handlers>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_absolute_path_static_handler</url>
<handler>
<type>static</type>
<content_type>text/html; charset=UTF-8</content_type>
<response_content>file:///absolute_path_file.html</response_content>
</handler>
</rule>
<rule>
<methods>GET</methods>
<headers><XXX>xxx</XXX></headers>
<url>/get_relative_path_static_handler</url>
<handler>
<type>static</type>
<content_type>text/html; charset=UTF-8</content_type>
<response_content>file://./relative_path_file.html</response_content>
</handler>
</rule>
</http_handlers>
$ user_files_path='/var/lib/clickhouse/user_files'
$ sudo echo "<html><body>Relative Path File</body></html>" > $user_files_path/relative_path_file.html
$ sudo echo "<html><body>Absolute Path File</body></html>" > $user_files_path/absolute_path_file.html
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_absolute_path_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_absolute_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:16 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=3
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
<
<html><body>Absolute Path File</body></html>
* Connection #0 to host localhost left intact
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_relative_path_static_handler'
* Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_relative_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:31 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=3
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0"}
<
<html><body>Relative Path File</body></html>
* Connection #0 to host localhost left intact
RT.WideStore поддерживает взаимодействие по протоколу MySQL. Данная функция включается настройкой mysql_port в конфигурационном файле:
<mysql_port>9004</mysql_port>
Пример подключения с помощью стандартного клиента mysql:
$ mysql --protocol tcp -u default -P 9004
Вывод в случае успешного подключения:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 20.2.1.1-ClickHouse
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
Для совместимости со всеми клиентами рекомендуется задавать пароль пользователя в конфигурационном файле с помощью двойного хэша SHA1.
В случае указания пароля с помощью SHA256 некоторые клиенты не смогут пройти аутентификацию (mysqljs и старые версии стандартного клиента mysql).
Ограничения:
ClickHouse поддерживает интерфейс gRPC. Это система удаленного вызова процедур с открытым исходным кодом, которая использует HTTP/2 и Protocol Buffers. В реализации gRPC в ClickHouse поддерживаются:
Спецификация интерфейса содержится в clickhouse_grpc.proto.
Чтобы сделать доступным интерфейс gRPC, нужно задать порт с помощью настройки grpc_port
в конфигурации сервера. Другие настройки приведены в примере:
<grpc_port>9100</grpc_port>
<grpc>
<enable_ssl>false</enable_ssl>
<!-- Пути к файлам сертификатов и ключей. Используются при включенном SSL -->
<ssl_cert_file>/path/to/ssl_cert_file</ssl_cert_file>
<ssl_key_file>/path/to/ssl_key_file</ssl_key_file>
<!-- Запрашивает ли сервер сертификат клиента -->
<ssl_require_client_auth>false</ssl_require_client_auth>
<!-- Используется, если необходимо запрашивать сертификат -->
<ssl_ca_cert_file>/path/to/ssl_ca_cert_file</ssl_ca_cert_file>
<!-- Алгоритм сжатия по умолчанию (применяется, если клиент не указывает алгоритм, см. result_compression в QueryInfo).
Поддерживаются алгоритмы: none, deflate, gzip, stream_gzip -->
<compression>deflate</compression>
<!-- Уровень сжатия по умолчанию (применяется, если клиент не указывает уровень сжатия, см. result_compression в QueryInfo).
Поддерживаемые уровни: none, low, medium, high -->
<compression_level>medium</compression_level>
<!-- Ограничение в байтах на размер отправляемых и принимаемых сообщений. -1 означает отсутствие ограничения -->
<max_send_message_size>-1</max_send_message_size>
<max_receive_message_size>-1</max_receive_message_size>
<!-- Выводить ли детализированные логи -->
<verbose_logs>false</verbose_logs>
</grpc>
Можно написать клиент на любом языке программирования, который поддерживается gRPC, с использованием спецификации. Также можно воспользоваться встроенным Python клиентом. Он расположен в utils/grpc-client/clickhouse-grpc-client.py в репозитории. Для работы встроенного клиента требуются Python модули grpcio и grpcio-tools.
Клиент поддерживает аргументы:
--help
– вывести справку и завершить работу.--host HOST, -h HOST
– имя сервера. Значение по умолчанию: localhost
. Можно задать адрес IPv4 или IPv6.--port PORT
– номер порта. Этот порт должен быть задан в конфигурации сервера ClickHouse настройкой grpc_port
. Значение по умолчанию: 9100
.--user USER_NAME, -u USER_NAME
– имя пользователя. Значение по умолчанию: default
.--password PASSWORD
– пароль. Значение по умолчанию: пустая строка.--query QUERY, -q QUERY
– запрос, который выполнится, когда используется неинтерактивный режим работы.--database DATABASE, -d DATABASE
– база данных по умолчанию. Если не указана, то будет использована база данных, заданная в настройках сервера (по умолчанию default
).--format OUTPUT_FORMAT, -f OUTPUT_FORMAT
– формат вывода результата. Значение по умолчанию для интерактивного режима: PrettyCompact
.--debug
– вывод отладочной информации.Чтобы запустить клиент в интерактивном режиме, не указывайте аргумент --query
.
В неинтерактивном режиме данные запроса можно передать через stdin
.
Пример использования клиента:
В примере создается таблица, и в нее загружаются данные из CSV файла. Затем выводится содержимое таблицы.
./clickhouse-grpc-client.py -q "CREATE TABLE grpc_example_table (id UInt32, text String) ENGINE = MergeTree() ORDER BY id;
"echo "0,Input data for" > a.txt ; echo "1,gRPC protocol example" >> a.txt
cat a.txt | ./clickhouse-grpc-client.py -q "INSERT INTO grpc_example_table FORMAT CSV"
./clickhouse-grpc-client.py --format PrettyCompact -q "SELECT * FROM grpc_example_table;"
Результат:
┌─id─┬─text───────────────────┐
│ 0 │ Input data for │
│ 1 │ gRPC protocol example │
└────┴─────────────────────────┘
Движок таблицы (тип таблицы) определяет:
Наиболее универсальные и функциональные движки таблиц для задач с высокой загрузкой. Общим свойством этих движков является быстрая вставка данных с последующей фоновой обработкой данных. Движки *MergeTree поддерживают репликацию данных (в Replicated* версиях движков), партиционирование, и другие возможности не поддержанные для других движков.
Движки семейства:
Простые движки с минимальной функциональностью. Они наиболее эффективны, когда вам нужно быстро записать много небольших таблиц (до примерно 1 миллиона строк) и прочитать их позже целиком.
Движки семейства:
Движки для связи с другими системами хранения и обработки данных.
Движки семейства:
Движки семейства:
Виртуальный столбец – это неотъемлемый атрибут движка таблиц, определенный в исходном коде движка.
Виртуальные столбцы не надо указывать в запросе CREATE TABLE и их не отображаются в результатах запросов SHOW CREATE TABLE и DESCRIBE TABLE. Также виртуальные столбцы доступны только для чтения, поэтому вы не можете вставлять в них данные.
Чтобы получить данные из виртуального столбца, необходимо указать его название в запросе SELECT. SELECT * не отображает данные из виртуальных столбцов.
При создании таблицы со столбцом, имя которого совпадает с именем одного из виртуальных столбцов таблицы, виртуальный столбец становится недоступным. Не делайте так. Чтобы помочь избежать конфликтов, имена виртуальных столбцов обычно предваряются подчеркиванием.
Выражения описывают различные действия, которые можно выполнить с помощью SQL запросов. Каждый вид выражения имеет свой синтаксис и особенности использования, которые описаны в Приложении 1 - Описание SQL выражений в RT.WideStore:
В системе есть два вида парсеров: полноценный парсер SQL (recursive descent parser) и парсер форматов данных (быстрый потоковый парсер).
Во всех случаях кроме запроса INSERT, используется только полноценный парсер SQL.
В запросе INSERT используется оба парсера:
INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')
Фрагмент INSERT INTO t VALUES парсится полноценным парсером, а данные (1, 'Hello, world'), (2, 'abc'), (3, 'def') - быстрым потоковым парсером.
Данные могут иметь любой формат. При получении запроса, сервер заранее считывает в оперативку не более max_query_size байт запроса (по умолчанию, 1МБ), а всё остальное обрабатывается потоково.
Таким образом, в системе нет проблем с большими INSERT запросами, как в MySQL.
При использовании формата Values в INSERT запросе может сложиться иллюзия, что данные парсятся также, как выражения в запросе SELECT, но это не так. Формат Values гораздо более ограничен.
Далее пойдёт речь о полноценном парсере. О парсерах форматов, смотри раздел «Форматы».
Между синтаксическими конструкциями (в том числе, в начале и конце запроса) может быть расположено произвольное количество пробельных символов. К пробельным символам относятся пробел, таб, перевод строки, CR, form feed.
Поддерживаются комментарии в SQL-стиле и C-стиле.
Комментарии в SQL-стиле: от -- до конца строки. Пробел после -- может не ставиться.
Комментарии в C-стиле: от /* до */. Такие комментарии могут быть многострочными. Пробелы тоже не обязательны.
Ключевые слова не зависят от регистра, если они соответствуют:
Зависимость от регистра для имён типов данных можно проверить в таблице system.data_type_families.
В отличие от стандарта SQL, все остальные ключевые слова, включая названия функций зависят от регистра.
Ключевые слова не зарезервированы (а всего лишь парсятся как ключевые слова в соответствующем контексте). Если вы используете идентификаторы, совпадающие с ключевыми словами, заключите их в кавычки. Например, запрос SELECT "FROM" FROM table_name валиден, если таблица table_name имеет столбец с именем "FROM".
Идентификаторы:
Некоторые идентификаторы нужно указывать в кавычках (например, идентификаторы с пробелами). Прочие идентификаторы можно указывать без кавычек. Рекомендуется использовать идентификаторы, не требующие кавычек.
Идентификаторы не требующие кавычек соответствуют регулярному выражению ^[a-zA-Z_][0-9a-zA-Z_]*$ и не могут совпадать с ключевыми словами. Примеры: x, _1, X_y__Z123_.
Если вы хотите использовать идентификаторы, совпадающие с ключевыми словами, или использовать в идентификаторах символы, не входящие в регулярное выражение, заключите их в двойные или обратные кавычки, например, "id", `id`.
Существуют: числовые, строковые, составные литералы и NULL.
Числовой литерал пытается распарситься:
Соответствующее значение будет иметь тип минимального размера, который вмещает значение.
Например, 1 парсится как UInt8, а 256 как UInt16. Подробнее о типах данных читайте в разделе Типы данных.
Примеры: 1, 18446744073709551615, 0xDEADBEEF, 01, 0.1, 1e100, -1e-100, inf, nan.
Поддерживаются только строковые литералы в одинарных кавычках. Символы внутри могут быть экранированы с помощью обратного слеша. Следующие escape-последовательности имеют соответствующее специальное значение: \b, \f, \r, \n, \t, \0, \a, \v, \xHH. Во всех остальных случаях, последовательности вида \c, где c – любой символ, преобразуется в c. Таким образом, могут быть использованы последовательности \' и \\. Значение будет иметь тип String.
Минимальный набор символов, которых вам необходимо экранировать в строковых литералах: ' и \. Одинарная кавычка может быть экранирована одинарной кавычкой, литералы 'It\'s' и 'It''s' эквивалентны.
Поддерживаются конструкции для массивов: [1, 2, 3] и кортежей: (1, 'Hello, world!', 2).
На самом деле, это вовсе не литералы, а выражение с оператором создания массива и оператором создания кортежа, соответственно.
Массив должен состоять хотя бы из одного элемента, а кортеж - хотя бы из двух.
Кортежи носят служебное значение для использования в секции IN запроса SELECT. Кортежи могут быть получены как результат запроса, но они не могут быть сохранены в базе данных (за исключением таблицы Memory.)
Обозначает, что значение отсутствует.
Чтобы в поле таблицы можно было хранить NULL, оно должно быть типа Nullable.
В зависимости от формата данных (входных или выходных) NULL может иметь различное представление. Подробнее смотрите в документации для форматов данных.
При обработке NULL есть множество особенностей. Например, если хотя бы один из аргументов операции сравнения – NULL, то результатом такой операции тоже будет NULL. Этим же свойством обладают операции умножения, сложения и пр. Подробнее читайте в документации на каждую операцию.
В запросах можно проверить NULL с помощью операторов IS NULL и IS NOT NULL, а также соответствующих функций isNull и isNotNull.
Функции записываются как идентификатор со списком аргументов (возможно, пустым) в скобках. В отличие от стандартного SQL, даже в случае пустого списка аргументов, скобки обязательны. Пример: now().
Бывают обычные и агрегатные функции (смотрите раздел «Агрегатные функции»). Некоторые агрегатные функции могут содержать два списка аргументов в круглых скобках. Пример: quantile(0.9)(x).
Такие агрегатные функции называются «параметрическими», а первый список аргументов называется «параметрами». Синтаксис агрегатных функций без параметров ничем не отличается от обычных функций.
Описание функций представлено в Приложении 2 (часть 1, часть 2, часть 3, часть 4, часть 5, часть 6) .
Операторы преобразуются в соответствующие им функции во время парсинга запроса, с учётом их приоритета и ассоциативности.
Например, выражение 1 + 2 * 3 + 4 преобразуется в plus(plus(1, multiply(2, 3)), 4).
Описание операторов представлено в Приложении 5.
Типы данных и движки таблиц в запросе CREATE записываются также, как идентификаторы или также как функции. То есть, могут содержать или не содержать список аргументов в круглых скобках. Подробнее смотрите разделы «Типы данных», «Движки таблиц», «CREATE».
Синоним – это пользовательское имя выражения в запросе:
expr AS alias
Где:
Синонимы являются глобальными для запроса или подзапроса, и вы можете определить синоним в любой части запроса для любого выражения. Например, SELECT (1 AS n) + 2, n.
Синонимы не передаются в подзапросы и между подзапросами. Например, при выполнении запроса SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a RT.WideStore сгенерирует исключение Unknown identifier: num.
Если синоним определен для результирующих столбцов в секции SELECT вложенного запроса, то эти столбцы отображаются во внешнем запросе. Например, SELECT n + m FROM (SELECT 1 AS n, 2 AS m).
Будьте осторожны с синонимами, совпадающими с именами столбцов или таблиц. Рассмотрим следующий пример:
CREATE TABLE t
(
a Int,
b Int
)
ENGINE = TinyLog()
SELECT
argMax(a, b),
sum(b) AS b
FROM t
Received exception from server (version 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: Aggregate
function sum(b) is found inside another aggregate function in query.
В этом примере мы объявили таблицу t со столбцом b. Затем, при выборе данных, мы определили синоним sum(b) AS b. Поскольку синонимы глобальные, то RT.WideStore заменил литерал b в выражении argMax(a, b) выражением sum(b). Эта замена вызвала исключение. Можно изменить это поведение, включив настройку prefer_column_name_to_alias, для этого нужно установить ее в значение 1
.
В запросе SELECT, вместо выражения может стоять звёздочка. Подробнее смотрите раздел «SELECT».
Выражение представляет собой функцию, идентификатор, литерал, применение оператора, выражение в скобках, подзапрос, звёздочку. А также может содержать синоним.
Список выражений – одно выражение или несколько выражений через запятую.
Функции и операторы, в свою очередь, в качестве аргументов, могут иметь произвольные выражения.
Запросы CREATE, DROP, ALTER, RENAME поддерживают возможность распределенного выполнения на кластере.
Например, следующий запрос создает распределенную (Distributed) таблицу all_hits на каждом хосте в cluster:
CREATE TABLE IF NOT EXISTS all_hits ON CLUSTER cluster (p Date, i Int32) ENGINE = Distributed(cluster, default, hits)
Для корректного выполнения таких запросов необходимо на каждом хосте иметь одинаковое определение кластера (для упрощения синхронизации конфигов можете использовать подстановки из ZooKeeper). Также необходимо подключение к ZooKeeper серверам.
Локальная версия запроса в конечном итоге будет выполнена на каждом хосте кластера, даже если некоторые хосты в данный момент не доступны. Гарантируется упорядоченность выполнения запросов в рамках одного хоста.
Функции бывают как минимум двух видов – обычные функции (называются просто, функциями) и агрегатные функции. Это совершенно разные вещи. Обычные функции работают так, как будто применяются к каждой строке по отдельности (для каждой строки, результат вычисления функции не зависит от других строк). Агрегатные функции аккумулируют множество значений из разных строк (то есть, зависят от целого множества строк).
В этом разделе речь пойдёт об обычных функциях. Для агрегатных функций, смотрите раздел «Агрегатные функции».
Примечание: Есть ещё третий вид функций, к которым относится функция arrayJoin; также можно отдельно иметь ввиду табличные функции.
В RT.WideStore, в отличие от стандартного SQL, типизация является строгой. То есть, не производится неявных преобразований между типами. Все функции работают для определённого набора типов. Это значит, что иногда вам придётся использовать функции преобразования типов.
Все выражения в запросе, имеющие одинаковые AST (одинаковую запись или одинаковый результат синтаксического разбора), считаются имеющими одинаковые значения. Такие выражения склеиваются и исполняются один раз. Одинаковые подзапросы тоже склеиваются.
Все функции возвращают одно (не несколько, не ноль) значение в качестве результата. Тип результата обычно определяется только типами аргументов, но не значениями аргументов. Исключение - функция tupleElement (оператор a.N), а также функция toFixedString.
Для простоты, некоторые функции могут работать только с константами в качестве некоторых аргументов. Например, правый аргумент оператора LIKE должен быть константой.
Почти все функции возвращают константу для константных аргументов. Исключение – функции генерации случайных чисел.
Функция now возвращает разные значения для запросов, выполненных в разное время, но результат считается константой, так как константность важна лишь в пределах одного запроса.
Константное выражение также считается константой (например, правую часть оператора LIKE можно сконструировать из нескольких констант).
Функции могут быть по-разному реализованы для константных и не константных аргументов (выполняется разный код). Но результат работы для константы и полноценного столбца, содержащего только одно такое же значение, должен совпадать.
Функции имеют следующие виды поведения:
Функции не могут поменять значения своих аргументов - любые изменения возвращаются в качестве результата. Соответственно, от порядка записи функций в запросе, результат вычислений отдельных функций не зависит.
Функции высшего порядка, в качестве своего функционального аргумента могут принимать только лямбда-функции. Чтобы передать лямбда-функцию в функцию высшего порядка, используйте оператор ->. Слева от стрелочки стоит формальный параметр – произвольный идентификатор, или несколько формальных параметров – произвольные идентификаторы в кортеже. Справа от стрелочки стоит выражение, в котором могут использоваться эти формальные параметры, а также любые столбцы таблицы.
Примеры:
x -> 2 * x
str -> str != Referer
В функции высшего порядка может быть передана лямбда-функция, принимающая несколько аргументов. В этом случае в функцию высшего порядка передаётся несколько массивов одинаковой длины, которым эти аргументы будут соответствовать.
Для некоторых функций первый аргумент (лямбда-функция) может отсутствовать. В этом случае подразумевается тождественное отображение.
Некоторые функции могут кидать исключения в случае ошибочных данных. В этом случае, выполнение запроса прерывается, и текст ошибки выводится клиенту. При распределённой обработке запроса, при возникновении исключения на одном из серверов, на другие серверы пытается отправиться просьба тоже прервать выполнение запроса.
В почти всех языках программирования, для некоторых операторов может не вычисляться один из аргументов. Обычно – для операторов &&, ||, ?:.
Но в RT.WideStore, аргументы функций (операторов) вычисляются всегда. Это связано с тем, что вычисления производятся не по отдельности для каждой строки, а сразу для целых кусочков столбцов.
При распределённой обработке запроса, как можно большая часть стадий выполнения запроса производится на удалённых серверах, а оставшиеся стадии (слияние промежуточных результатов и всё, что дальше) - на сервере-инициаторе запроса.
Это значит, что выполнение функций может производиться на разных серверах.
Например, в запросе SELECT f(sum(g(x))) FROM distributed_table GROUP BY h(y),
Обычно результат выполнения функции не зависит от того, на каком сервере её выполнить. Но иногда это довольно важно.
Например, функции, работающие со словарями, будут использовать словарь, присутствующий на том сервере, на котором они выполняются.
Другой пример – функция hostName вернёт имя сервера, на котором она выполняется, и это можно использовать для служебных целей - чтобы в запросе SELECT сделать GROUP BY по серверам.
Если функция в запросе выполняется на сервере-инициаторе запроса, а вам нужно, чтобы она выполнялась на удалённых серверах, вы можете обернуть её в агрегатную функцию any или добавить в ключ в GROUP BY.
Форматы входных и выходных данных RT.WideStore.