Skip to content
1 change: 1 addition & 0 deletions ydb/docs/ru/core/concepts/transfer.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,4 @@
* [CREATE TRANSFER](../yql/reference/syntax/create-transfer.md)
* [ALTER TRANSFER](../yql/reference/syntax/alter-transfer.md)
* [DROP TRANSFER](../yql/reference/syntax/drop-transfer.md)
* [{#T}](../recipes/transfer/index.md)
1 change: 1 addition & 0 deletions ydb/docs/ru/core/recipes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
* [{#T}](ydb-sdk/index.md)
* [{#T}](ydb-cli/index.md)
* [{#T}](../yql/reference/recipes/index.md)
* [{#T}](transfer/index.md)
5 changes: 5 additions & 0 deletions ydb/docs/ru/core/recipes/toc_p.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ items:
include:
mode: link
path: vector-search/toc_p.yaml
- name: Трансфер
href: transfer/index.md
include:
mode: link
path: transfer/toc_p.yaml
2 changes: 2 additions & 0 deletions ydb/docs/ru/core/recipes/transfer/_includes/batching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Строки в таблицу добавляются не на каждое сообщение, полученное из топика, а предварительно батчуются. По умолчанию интервал записи в таблицу составляет 60 сек., либо объем записываемых данных должен достигнуть 8 Mb. Параметры батчевания можно явно задать при [создании](../../../yql/reference/syntax/create-transfer.md) трансфера либо [измененить](../../../yql/reference/syntax/alter-transfer.md) их позже.

8 changes: 8 additions & 0 deletions ydb/docs/ru/core/recipes/transfer/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Рецепты работы с трансфером данных из топика в таблицу

Этот раздел содержит рецепты работы с [трансфером](../../concepts/transfer.md) из топика в таблицу.

Содержание:

* [{#T}](transfer-quickstart.md)
* [{#T}](transfer-nginx.md)
5 changes: 5 additions & 0 deletions ydb/docs/ru/core/recipes/transfer/toc_p.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
items:
- name: Трансфер - быстрый старт
href: transfer-quickstart.md
- name: Трансфер — поставка access логов NGINX в таблицу
href: transfer-nginx.md
160 changes: 160 additions & 0 deletions ydb/docs/ru/core/recipes/transfer/transfer-nginx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Трансфер — поставка access логов NGINX в таблицу

Эта статья поможет настроить поставку access логов NGINX в [таблицу](../../concepts/datamodel/table.md) для дальнейшего анализа. В этой статье будет рассматриваться формат access логов NGINX, который используется по умолчанию. Более подробно о формате логов NGINX и его настройке можно прочитать в [документации](https://docs.nginx.com/nginx/admin-guide/monitoring/logging/#set-up-the-access-log) NGINX.

Формат access лога NGINX по умолчанию имеет вид:

```txt
$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"
```

Пример:

```txt
::1 - - [01/Sep/2025:15:02:47 +0500] "GET /favicon.ico HTTP/1.1" 404 181 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36"
::1 - - [01/Sep/2025:15:02:51 +0500] "GET / HTTP/1.1" 200 409 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36"
::1 - - [01/Sep/2025:15:02:51 +0500] "GET /favicon.ico HTTP/1.1" 404 181 "http://localhost/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36"
```

В статье будут рассмотрены следующие шаги:

* [создание таблицы](#step1) в которую будут записываться данные;
* [создание трансфера](#step2);
* [проверка содержимого таблицы](#step3).

## Пререквизиты

Для выполнения примеров из этой статьи понадобятся:

* Установленная БД {{ ydb-short-name }} версии 25-2 или выше. Об установке простого одноузлового кластера {{ ydb-short-name }} можно прочитать [здесь](../../quickstart.md). Рекомендации по развёртыванию {{ ydb-short-name }} для промышленного использования см. [здесь](../../devops/deployment-options/index.md?version=main).

* Установленный http-сервер NGINX с ведением access логов или access логи NGINX доступные с другого сервера.

* Настроенная поставка access логов NGINX из файла в топик `transfer_recipe/access_log_topic`, например, с помощью [kafka connect](../../reference/kafka-api/connect/index.md) с [конфигурацией](../../reference/kafka-api/connect/connect-examples.md#file-to-topic) поставки данных из файла в топик.

## Шаг 1. Создание таблицы {#step1}

Добавьте [таблицу](../../concepts/datamodel/table.md), в которую будут поставляться данные из топика `transfer_recipe/access_log_topic`. Это можно сделать с помощью [SQL-запроса](../../yql/reference/syntax/create_table/index.md):

```yql
CREATE TABLE `transfer_recipe/access_log` (
partition Uint32 NOT NULL,
offset Uint64 NOT NULL,
line Uint64 NOT NULL,
remote_addr String,
remote_user String,
time_local Timestamp,
request_method String,
request_path String,
request_protocol String,
status Uint32,
body_bytes_sent Uint64,
http_referer String,
http_user_agent Utf8,
PRIMARY KEY (partition, offset, line)
);
```

Эта таблица `transfer_recipe/access_log` имеет три служебных столбца:

* `partition` — идентификатор [партиции](../../concepts/glossary.md#partition) топика, из которой получено сообщение;
* `offset` — [порядковый номер](../../concepts/glossary.md#offset), идентифицирующий сообщение внутри партиции;
* `line` — порядковый номер строки лога внутри сообщения.

Столбцы `partition`, `offset` и `line` однозначно идентифицируют строку файла access лога.

Если требуется хранить данные access логов ограниченное кол-во времени, то можно настроить [автоматическое удаление](../../concepts/ttl.md) старых строк таблицы. Это можно сделать с помощью [SQL-запроса](../../yql/reference/recipes/ttl.md):

```yql
ALTER TABLE `transfer_recipe/access_log` SET (TTL = Interval("PT24H") ON time_local);
```

## Шаг 2. Создание трансфера {#step2}

После создания топика и таблицы следует добавить [трансфер](../../concepts/transfer.md) данных, который будет перекладывать сообщения из топика в таблицу. Это можно сделать с помощью [SQL-запроса](../../yql/reference/syntax/create-transfer.md):

```yql
$transformation_lambda = ($msg) -> {
-- Функция преобразования строки лога в строку таблицы
$line_lambda = ($line) -> {
-- Сначала разбиваем строку по символу " (двойные кавычки) чтобы выделить строки, которые могут содержать пробел.
-- Сами строки символ " (двойные кавычки) содержать не могут - он будет зменен последовательностью символов \x.
$parts = String::SplitToList($line.1, '"');
-- Каждую полученную часть, которая не соответствует экранированной строке, разбиваем по пробелу.
$info_parts = String::SplitToList($parts[0], " ");
$request_parts = String::SplitToList($parts[1], " ");
$response_parts = String::SplitToList($parts[2], " ");
-- Преобразуем дату в Datetime тип
$dateParser = DateTime::Parse("%d/%b/%Y:%H:%M:%S");
$date = $dateParser(Substring($info_parts[3], 1));

-- Возвращаем структуру, каждое именованное поле которой соответствует столбцу таблицы.
-- Важно: типы значений именованных полей должны соответствовать типам столбцов таблицы, например, если столбец имеет тип Uint32,
-- то значение именованного поля должно быть Uint32. Иначе потребуется явное преобразование с помощью CAST.
-- Значение NOT NULL колонок должно быть преобразовано из опционального типа с помощью функции Unwrap.
return <|
partition: $msg._partition,
offset: $msg._offset,
line: $line.0,
remote_addr: $info_parts[0],
remote_user: $info_parts[2],
time_local: DateTime::MakeTimestamp($date),
request_method: $request_parts[0],
request_path: $request_parts[1],
request_protocol: $request_parts[2],
status: CAST($response_parts[1] AS Uint32),
body_bytes_sent: CAST($response_parts[2] AS Uint64),
http_referer: $parts[3],
http_user_agent: CAST($parts[5] AS Utf8) -- явно преобразовываем в Utf8 т.к. колонка http_user_agent имеет типа Utf8, а не String
|>;
};


$split = String::SplitToList($msg._data, "\n"); -- Если одно сообщение содержит несколько строк из лога, то разделяем сообщение на отельные строки
$lines = ListFilter($split, ($line) -> { -- Фильтруем пустые строки, которые, например, могут появится после последнего символа \n
return Length($line) > 0;
});

-- Преобразуем каждую строку access лога в строку таблицы
return ListMap(ListEnumerate($lines), $line_lambda);
};

CREATE TRANSFER `transfer_recipe/access_log_transfer`
FROM `transfer_recipe/access_log_topic` TO `transfer_recipe/access_log`
USING $transformation_lambda;
```

В этом примере:

* `$transformation_lambda` - это правило преобразования сообщения из топика в колонки таблицы. Каждая строка access лога, записанная в сообщение, обрабатывается отдельно при помощи `line_transformation_lambda`;
* `$line_lambda`- это правило преобразование одной строки access лога в строку таблицы;
* `$msg` - переменная, которая содержит обрабатываемое сообщение из топика.

## Шаг 3. Проверка содержимого таблицы {#step3}

После записи сообщении в топик `transfer_recipe/access_log_topic` спустя некоторое время появятся записи в таблице `transfer_recipe/access_log`. Проверить их наличие можно с помощью [SQL-запроса](../../yql/reference/syntax/select/index.md):

```yql
SELECT *
FROM `transfer_recipe/access_log`;
```

Результат выполнения запроса:

```txt
# partition offset line remote_addr remote_user time_local request_method request_path request_protocol status body_bytes_sent http_referer http_user_agent
1 0 2 0 ::1 - 2025-09-01T15:02:51.000000Z GET /favicon.ico HTTP/1.1 404 181 http://localhost/ Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36
2 0 1 0 ::1 - 2025-09-01T15:02:51.000000Z GET / HTTP/1.1 200 409 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36
3 0 0 0 ::1 - 2025-09-01T15:02:47.000000Z GET /favicon.ico HTTP/1.1 404 181 - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 YaBrowser/25.6.0.0 Safari/537.36
```

{% include [x](_includes/batching.md) %}

## Заключение

Данная статья приводит пример поставки access логов NGINX в таблицу {{ ydb-short-name }}. Логи любого другого текстовового формата могут обрабатываться аналогично: для этого надо создать таблицу, в которой будут храниться необходимые данные из этого лога, и правильно написать [lambda-функции](../../yql/reference/syntax/expressions.md#lambda), преобразовывающую строки лога в строки таблицы.

См. также:

* [{#T}](../../concepts/transfer.md)
* [{#T}](transfer-quickstart.md)
108 changes: 108 additions & 0 deletions ydb/docs/ru/core/recipes/transfer/transfer-quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Трансфер — быстрый старт

Эта статья поможет быстро начать работу с [трансфером](../../concepts/transfer.md) в {{ ydb-short-name }} на простейшем модельном примере.

В статье будут рассмотрены следующие шаги работы с трансфером:

* [создание топика](#step1) из которого будет читать трансфер;
* [создание таблицы](#step2) в которую будут записываться данные;
* [создание трансфера](#step3);
* [заполнение топика данными](#step4);
* [проверка содержимого таблицы](#step5).

## Шаг 1. Создание топика {#step1}

Сначала нужно создать [топик](../../concepts/datamodel/topic.md) в {{ ydb-short-name }}, из которого трансфер будет читать данные. Это можно сделать с помощью [SQL-запроса](../../yql/reference/syntax/create-topic.md):

```yql
CREATE TOPIC `transfer_recipe/source_topic`;
```

Этот топик `transfer_recipe/source_topic` позволяет передавать любые неструктурированные данные.

## Шаг 2. Создание таблицы {#step2}

После создания топика следует добавить [таблицу](../../concepts/datamodel/table.md), в которую будут поставляться данные из топика `source_topic`. Это можно сделать с помощью [SQL-запроса](../../yql/reference/syntax/create_table/index.md):

```yql
CREATE TABLE `transfer_recipe/target_table` (
partition Uint32 NOT NULL,
offset Uint64 NOT NULL,
data String,
PRIMARY KEY (partition, offset)
);
```

Эта таблица `transfer_recipe/target_table` имеет три столбца:

* `partition` — идентификатор [партиции](../../concepts/glossary.md#partition) топика, из которой получено сообщение;
* `offset` — [порядковый номер](../../concepts/glossary.md#offset), идентифицирующий сообщение внутри партиции;
* `data` — тело сообщения.

## Шаг 3. Создание трансфера {#step3}

После создания топика и таблицы следует добавить [трансфер](../../concepts/transfer.md) данных, который будет перекладывать сообщения из топика в таблицу. Это можно сделать с помощью [SQL-запроса](../../yql/reference/syntax/create-transfer.md):

```yql
$transformation_lambda = ($msg) -> {
return [
<|
partition: $msg._partition,
offset: $msg._offset,
data: $msg._data
|>
];
};

CREATE TRANSFER `transfer_recipe/example_transfer`
FROM `transfer_recipe/source_topic` TO `transfer_recipe/target_table`
USING $transformation_lambda;
```

В этом примере:

* `$transformation_lambda` - это правило преобразования сообщения из топика в колонки таблицы. В данном примере сообщение топика переносится в таблицу без преобразований;
* `$msg` - переменная, которая содержит обрабатываемое сообщение из топика.

## Шаг 4. Заполнение топика данными {#step4}

После создания трансфера можно записать в топик сообщение, например, используя [{{ ydb-short-name }} CLI](../../reference/ydb-cli/index.md).

{% include [x](../../_includes/ydb-cli-profile.md) %}

```bash
echo "Message 1" | ydb --profile quickstart topic write source_topic
echo "Message 2" | ydb --profile quickstart topic write source_topic
echo "Message 3" | ydb --profile quickstart topic write source_topic
```

## Шаг 5. Проверка содержимого таблицы {#step5}

После записи сообщении в топик `source_topic` спустя некоторое время появятся записи в таблице `transfer_recipe/target_table`. Проверить их наличие можно с помощью [SQL-запроса](../../yql/reference/syntax/select/index.md):

```yql
SELECT *
FROM `transfer_recipe/target_table`;
```

Результат выполнения запроса:

```bash
partition offset data
0 0 "Message 1"
0 1 "Message 2"
0 2 "Message 3"
```

{% include [x](_includes/batching.md) %}

## Заключение

Данная статья приводит простой пример работы с трансфером: создание топика, таблицы и трансфера, записи в топик и проверки результата работы трансфера.

Эти примеры призваны проиллюстрировать синтаксис при работе с трансфером. Более реалистичный пример см. в [статье](transfer-nginx.md) описывающей поставку access лога NGINX.

См. также:

* [{#T}](../../concepts/transfer.md)
* [{#T}](transfer-nginx.md)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

В разделе приведены примеры файлов настройки коннекторов Kafka Connect для работы с {{ ydb-short-name }} по протоколу Kafka.

## Из файла в {{ ydb-short-name }}
## Из файла в {{ ydb-short-name }} {#file-to-topic}

Пример файла настроек FileSource коннектора `/etc/kafka-connect-worker/file-sink.properties` для переноса данных из файла в топик:

Expand Down