/datamarts[/{datamart}]/query-upload
Содержание раздела
POST-метод выполняет SELECT-запрос с табличным параметром.
В отличие от /query, который для SELECT-запросов использует только существующие в системе данные, /query-upload позволяет временно загрузить дополнительные данные и исполнить запрос с их учетом.
Запросы с табличным параметром через /query-upload поддерживаются только для ADP и ADB.
Режимы чтения данных
Метод поддерживает режимы чтения данных:
- однократное чтение — возвращается один ответ с полной выборкой по запросу;
- потоковое чтение — возвращается поток ответов с порциями данных.
По умолчанию возвращается один ответ. Чтобы получить ответ в виде потока, задайте размер порций данных в теле запроса (см. fetchSize).
Потоковое чтение данных по HTTP API доступно только для HTTP/2. Подробнее см. в разделе Потоковое чтение данных.
Условные обозначения
В описании метода используются обозначения:
{value}— значение параметра;[element]или[ element ]— опциональный элемент.
URL
{baseUrl}/api/v1/datamarts[/{datamart}]/query-upload[?format={format}[&compressionLevel={level}]][&queryId={queryId}]
{baseUrl}
Адрес ноды Prostore, состоящий из IP-адреса или доменного имени и номера порта.
[ {datamart} ]
Имя логической базы данных, используемой по умолчанию. Если не указано, должно быть указано в query для каждой сущности отдельно.
[ format ]
Формат ответа. Возможные значения:
json— JSON-строка (по умолчанию);plain— текстовое представление;avro— Avro-формат без сжатия;avro-deflate— Avro-формат со сжатием по алгоритму Deflate;avro-snappy— Avro-формат со сжатием по алгоритму Snappy;avro-bzip2— Avro-формат со сжатием по алгоритму BZip2;avro-xz— Avro-формат со сжатием по алгоритму XZ;avro-zstandard— Avro-формат со сжатием по алгоритму Zstandard.
[ compressionLevel ]
Коэффициент сжатия данных.
Должен быть указан, если в format задан Avro-формат со сжатием. Возможные значения коэффициента зависят от выбранного алгоритма сжатия; подробнее см. в документации Apache Avro.
[ queryId ]
Идентификатор, по которому можно отследить обработку запроса с помощью логов.
Параметр влияет на выбор датасорса для исполнения запроса. Запросы с одинаковым значением queryId исполняются в одном и том же датасорсе, если он остается включен и набор подходящих датасорсов не меняется.
Альтернативно queryId можно указать в теле запроса. Если заданы оба, они должны совпадать, иначе возвращается ошибка.
Заголовки запроса
x-json-part-size
Задает точный размер JSON-части в байтах (в кодировке UTF-8), помещенной в начало бинарного тела сообщения. Значение должно быть точным, так как по нему система определяет границу между параметрами запроса и данными табличного параметра.
[ x-request-id ]
Задает уникальный идентификатор HTTP-запроса. Если не указан, система генерирует UUID-значение и возвращает его в качестве идентификатора в ответе.
Content-Type
Задает формат данных в теле запроса. Возможные значения:
application/octet-stream— бинарный формат.
Тело запроса
Тело запроса представлено в бинарном виде и состоит из двух частей (см. схему ниже):
- [первые x-json-part-size байтов] JSON-часть в кодировке UTF-8 с параметрами, управляющими исполнением запроса, включая структуру табличного параметра;
- [байты после x-json-part-size] Avro-часть с данными табличного параметра.
Составные части запроса
Avro-часть должна представлять собой корректный Avro-файл, с заголовком, описывающим схему данных, и блоками данных. Данные могут быть упакованы без сжатия или со сжатием по любому алгоритму и отправлены в Prostore одной порцией или потоком. Степень и алгоритм сжатия указывать не нужно.
query
SELECT-запрос.
Значения в запросе можно указать как константы или параметры в любом сочетании.
[ queryId ]
Идентификатор, по которому можно отследить обработку запроса с помощью логов.
Параметр влияет на выбор датасорса для исполнения запроса. Запросы с одинаковым значением queryId исполняются в одном и том же датасорсе, если он остается включен и набор подходящих датасорсов не меняется.
Альтернативно queryId можно указать в URL. Если заданы оба, они должны совпадать, иначе возвращается ошибка.
[ sqlRequestPriority ]
Приоритет, назначаемый запросу и определяющий порядок его балансировки.
Если отсутствует:
- запросу назначается приоритет по умолчанию (
READ_BALANCE_SQL_REQUEST_PRIORITY) — если он задан в конфигурации; - запрос обрабатывается без балансировки — иначе.
Запрос также обрабатывается без балансировки, если для его приоритета нет подходящих настроек балансировки.
[ maxRowsToRead ]
Максимальное число записей, возвращаемых по запросу. При потоковом чтении учитывает все порции данных.
Если параметр не задан, равен 0 или null, число записей не ограничено.
[ fetchSize ]
Максимальное число записей в порции данных, возвращаемой в одном ответе при потоковом чтении.
Если параметр не задан, равен 0 или null, все записи возвращаются одним ответом (потоковое чтение выключено).
Потоковое чтение доступно только для HTTP/2. Подробнее см. в разделе Потоковое чтение данных.
[ fetchTimeoutMs ]
Максимальное время, выделяемое на исполнение SELECT-запроса в системе. Указывается в миллисекундах и применяется как при обычном чтении (одной порцией со всей выборкой), так и потоковом.
Время отсчитывается с момента получения запроса системой до завершения передачи всех запрошенных данных. При превышении лимита система принудительно завершает запрос.
Если параметр не задан, равен 0 или null, время исполнения не ограничено.
[ params ]
Список параметров запроса. Может содержать максимум один табличный параметр и неограниченное число параметров других типов.
Применимые поля в зависимости от типа параметра см. в таблице ниже.
| Поле | Описание | Параметры, для которых применимо поле | |||
|---|---|---|---|---|---|
| Индексированные | Именованные | Системные | Табличные | ||
name | Имя параметра | – | + | + | + |
value | Значение параметра | + | + | + | – |
type | Тип данных параметра | + | + | + | – |
columns | Список столбцов табличного параметра | – | – | – | + |
columns/name | Имя столбца в табличном параметре | – | – | – | + |
columns/type | Тип данных столбца в табличном параметре | – | – | – | + |
Пример JSON-части
В примере ниже показана JSON-часть тела запроса. Для наглядности она показана в незакодированном виде, но в реальном запросе она должна быть в UTF-8.
SELECT-запрос в query фильтрует строки таблицы marketing.sales по двум столбцам (на основе значений табличного параметра store_and_product_filter) и условию на транзакции за предыдущий месяц.
{
"query": "SELECT s.* FROM marketing.sales s JOIN @store_and_product_filter ON s.store_id = @store_and_product_filter.store_id AND s.product_code = @store_and_product_filter.product_code WHERE s.transaction_date >= DATE_TRUNC(MONTH, TIMESTAMPADD(MONTH, -1, current_date)) AND s.transaction_date < DATE_TRUNC(MONTH, current_date) DATASOURCE_TYPE = '\''adp'\''",
"params": [
{
"name": "store_and_product_filter",
"columns": [
{ "name": "store_id", "type": "LONG" },
{ "name": "product_code", "type": "STRING" }
]
}
],
"queryId": "5345678",
"maxRowsToRead": 100,
"fetchSize": 100,
"fetchTimeoutMs": 30000
}
Формат и состав ответа
Поддерживаемые форматы данных
Метод возвращает данные в одном из форматов: JSON, Avro или plain. По умолчанию ответ возвращается в JSON-формате. Чтобы выбрать другой формат ответа, задайте параметр format в URL.
Avro-формат ответа
В Avro-ответе элемент doc схемы Avro описывает логические типы данных, содержащихся в выборке (см. пример ниже).
Для столбца с неопределенным типом данных в doc указывается тип ANY, а в fields — union-элемент со всеми типами Avro, как показано для test_column ниже. Пример запроса с неопределенным типом данных у столбца test_column: SELECT *, null AS test_column FROM marketing.sales.
Пример схемы Avro в ответе, представленной для наглядности в JSON-формате:
{
"type": "record",
"name": "QueryResultRow",
"namespace": "query.result",
"doc": {
"metadata": [
{
"name": "id",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "transaction_date",
"type": "TIMESTAMP",
"size": 6,
"nullable": false
},
{
"name": "product_code",
"type": "VARCHAR",
"size": 256,
"nullable": false
},
{
"name": "product_units",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "store_id",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "description",
"type": "VARCHAR",
"size": 256,
"nullable": true
},
{
"name": "test_column",
"type": "ANY",
"size": null,
"nullable": true
}
]
},
"fields": [
{"name": "id", "type": "long"},
{"name": "transaction_date", "type": {"type": "long", "logicalType": "timestamp-micros"}},
{"name": "product_code", "type": {"type": "string", "avro.java.string": "String"}},
{"name": "product_units", "type": "long"},
{"name": "store_id", "type": "long"},
{"name": "description", "type": ["null", {"type": "string", "avro.java.string": "String"}], "default": null},
{"name" : "test_column", "type" : [ "null", "long", "double", "int", "float", "boolean", {"type" : "string", "avro.java.string" : "String"}], "default" : null}
]
}
Состав ответов при потоковом чтении данных
Состав ответов при потоковом чтении данных зависит от заданного формата ответа:
- в plain-формате:
- [первый ответ] содержит список имен столбцов, присутствующих в выборке;
- [последующие ответы] содержат порции записей без метаданных;
- в Avro-формате:
- [первый ответ] содержит заголовок со схемой данных Avro (см. пример выше);
- [последующие ответы] содержат блоки данных без заголовка и схемы;
- в JSON-формате — состав ответов см. в таблице ниже, пример ответов — в секции Пример потока в ответе в JSON-формате.
| Элемент ответа (JSON) | Первый ответ | Последующие ответы, кроме последнего | Последний ответ |
|---|---|---|---|
queryId | Значение queryId | null | Значение queryId |
rows | null | null | Итоговое количество строк в ResultSet (с учетом всех порций записей) |
statistics | null | null |
|
metadata | Логическая схема данных (столбцы ResultSet) | null | null |
result | null | Порция записей (строки ResultSet) | Порция записей (строки ResultSet) |
Пример ответного потока в JSON-формате
Ниже показан пример потока данных в JSON-формате в ответ на SELECT-запрос к таблице marketing.sales.
Первый ответ в потоке ответов:
{
"queryId": "84706c2d-ba4a-4bb5-85e3-a367090f5882",
"rows": null,
"statistics": null,
"metadata": [
{
"name": "id",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "transaction_date",
"type": "TIMESTAMP",
"size": 6,
"nullable": false
},
{
"name": "product_code",
"type": "VARCHAR",
"size": 256,
"nullable": false
},
{
"name": "product_units",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "store_id",
"type": "BIGINT",
"size": null,
"nullable": false
},
{
"name": "description",
"type": "VARCHAR",
"size": 256,
"nullable": true
}
],
"result": null
}
Следующий ответ в потоке ответов:
{
"queryId": null,
"rows": null,
"statistics": null,
"metadata": null,
"result": [
{
"id": 300123,
"transaction_date": "2023-08-22 13:17:47",
"product_code": "ABC0002",
"product_units": 4,
"store_id": 123,
"description": "Покупка по акции \"Лето\""
},
{
"id": 300021,
"transaction_date": "2023-08-21 23:34:10",
"product_code": "ABC0001",
"product_units": 2,
"store_id": 123,
"description": "Покупка по акции \"1+1\""
},
{
"id": 300133,
"transaction_date": "2023-08-23 18:01:04",
"product_code": "ABC0002",
"product_units": 4,
"store_id": 123,
"description": "Покупка по акции \"Лето\""
}
]
}
Последний ответ в потоке с остатком записей, число которых может быть меньше fetchSize:
{
"queryId": "84706c2d-ba4a-4bb5-85e3-a367090f5882",
"rows": 59,
"statistics" : {
"elapsedTotalMs" : 1522,
"elapsedDbMs" : 364
},
"metadata": null,
"result": [
{
"id": 300031,
"transaction_date": "2021-08-25 15:34:10",
"product_code": "ABC0001",
"product_units": 2,
"store_id": 123,
"description": "Покупка по акции \"1+1\""
},
{
"id": 11,
"transaction_date": "2021-09-11 10:23:40",
"product_code": "ABC0004",
"product_units": 2,
"store_id": 123,
"description": "Покупка по акции \"1+1\""
}
]
}
Порядок обработки запроса
Prostore обрабатывает запрос в следующем порядке:
- Разделяет JSON- и Avro-части тела запроса по значению заголовка
x-json-part-size. - Создает временную таблицу в датасорсе, выбранном для исполнения запроса. Таблица создается внутри транзакции СУБД и имеет структуру, заданную для табличного параметра.
- Загружает данные табличного параметра во временную таблицу:
- Принимает порции данных от внешней системы и записывает их в буфер сырых данных.
- Из полученных порций данных выделяет записи и сохраняет их в буфер подготовленных записей.
- Накапливает подготовленные записи в пачки.
- По мере накопления загружает пачки записей в созданную временную таблицу.
- Исполняет запрос, указанный в
query:- При успешной загрузке всех записей из переданного потока данных:
- Исполняет запрос с загруженными данными табличного параметра.
- Возвращает ResultSet с результатами запроса:
- [fetchSize = 0 или не задан] одним ответом;
- [fetchSize > 0] потоком ответов, размер каждого из которых равен
fetchSize(последний ответ может быть меньше, так как содержит остаток записей).
- При прерывании загрузки возвращает неуспешный ответ с кодом 500.
- При успешной загрузке всех записей из переданного потока данных:
- Удаляет временную таблицу.
Размеры буферов и пачек записей настраиваются в конфигурации нод с помощью параметров STREAMING_UPLOAD_INPUT_BUFFER_SIZE_MB, STREAMING_UPLOAD_DB_BUFFER_SIZE и STREAMING_UPLOAD_DB_BATCH_SIZE.
Ограничения
- Секция запроса
paramsможет содержать максимум 1 табличный параметр; иначе — ошибка. При этом параметр может использоваться неограниченное число раз в SELECT-запросе секцииquery. - Для табличного параметра игнорируются:
- выражения FOR SYSTEM_TIME, указанные в SELECT-запросе;
- системные параметры, указанные в секции
params.