/datamarts[/{datamart}]/query-upload

Содержание раздела
  1. Режимы чтения данных
  2. Условные обозначения
  3. URL
    1. {baseUrl}
    2. [ {datamart} ]
    3. [ format ]
    4. [ compressionLevel ]
    5. [ queryId ]
  4. Заголовки запроса
    1. x-json-part-size
    2. [ x-request-id ]
    3. Content-Type
  5. Тело запроса
    1. query
    2. [ queryId ]
    3. [ sqlRequestPriority ]
    4. [ maxRowsToRead ]
    5. [ fetchSize ]
    6. [ fetchTimeoutMs ]
    7. [ params ]
    8. Пример JSON-части
  6. Формат и состав ответа
    1. Поддерживаемые форматы данных
    2. Avro-формат ответа
    3. Состав ответов при потоковом чтении данных
      1. Пример ответного потока в JSON-формате
  7. Порядок обработки запроса
  8. Ограничения

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 — бинарный формат.

Тело запроса

Тело запроса представлено в бинарном виде и состоит из двух частей (см. схему ниже):

  1. [первые x-json-part-size байтов] JSON-часть в кодировке UTF-8 с параметрами, управляющими исполнением запроса, включая структуру табличного параметра;
  2. [байты после x-json-part-size] Avro-часть с данными табличного параметра.

Составные части запроса

Avro-часть должна представлять собой корректный Avro-файл, с заголовком, описывающим схему данных, и блоками данных. Данные могут быть упакованы без сжатия или со сжатием по любому алгоритму и отправлены в Prostore одной порцией или потоком. Степень и алгоритм сжатия указывать не нужно.

query

SELECT-запрос.

Значения в запросе можно указать как константы или параметры в любом сочетании.

[ queryId ]

Идентификатор, по которому можно отследить обработку запроса с помощью логов.

Параметр влияет на выбор датасорса для исполнения запроса. Запросы с одинаковым значением queryId исполняются в одном и том же датасорсе, если он остается включен и набор подходящих датасорсов не меняется.

Альтернативно queryId можно указать в URL. Если заданы оба, они должны совпадать, иначе возвращается ошибка.

[ sqlRequestPriority ]

Приоритет, назначаемый запросу и определяющий порядок его балансировки.

Если отсутствует:

Запрос также обрабатывается без балансировки, если для его приоритета нет подходящих настроек балансировки.

[ 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
  • elapsedTotalMs — общее время, прошедшее от получения запроса до отправки последнего ответа;
  • elapsedDbMs — общее время исполнения всех запросов в СУБД
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 обрабатывает запрос в следующем порядке:

  1. Разделяет JSON- и Avro-части тела запроса по значению заголовка x-json-part-size.
  2. Создает временную таблицу в датасорсе, выбранном для исполнения запроса. Таблица создается внутри транзакции СУБД и имеет структуру, заданную для табличного параметра.
  3. Загружает данные табличного параметра во временную таблицу:
    1. Принимает порции данных от внешней системы и записывает их в буфер сырых данных.
    2. Из полученных порций данных выделяет записи и сохраняет их в буфер подготовленных записей.
    3. Накапливает подготовленные записи в пачки.
    4. По мере накопления загружает пачки записей в созданную временную таблицу.
  4. Исполняет запрос, указанный в query:
    • При успешной загрузке всех записей из переданного потока данных:
      1. Исполняет запрос с загруженными данными табличного параметра.
      2. Возвращает ResultSet с результатами запроса:
        • [fetchSize = 0 или не задан] одним ответом;
        • [fetchSize > 0] потоком ответов, размер каждого из которых равен fetchSize (последний ответ может быть меньше, так как содержит остаток записей).
    • При прерывании загрузки возвращает неуспешный ответ с кодом 500.
  5. Удаляет временную таблицу.

Размеры буферов и пачек записей настраиваются в конфигурации нод с помощью параметров 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.