Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Настройка эндпоинтов Query API

Возможность эндпоинты Query API позволяет создавать API-конечные точки напрямую из любого сохранённого SQL-запроса в консоли ClickHouse Cloud. Вы сможете обращаться к API-конечным точкам по HTTP, чтобы выполнять сохранённые запросы без необходимости подключаться к своему сервису ClickHouse Cloud через нативный драйвер.

Предварительные требования

Прежде чем продолжить, убедитесь, что у вас есть:

  • API-ключ с соответствующими разрешениями
  • роль Admin в консоли

Если у вас ещё нет API-ключа, воспользуйтесь этим руководством, чтобы создать API-ключ.

Создание сохраненного запроса

Если у вас уже есть сохраненный запрос, этот шаг можно пропустить.

Откройте новую вкладку запроса. Для примера мы будем использовать датасет YouTube, который содержит примерно 4,5 миллиарда записей. Следуйте инструкциям в разделе "Create table", чтобы создать таблицу в вашем сервисе Cloud и вставить в нее данные.

В качестве примера мы получим 10 лучших загрузчиков по среднему числу просмотров на видео с параметром year, который задает пользователь.

WITH sum(view_count) AS view_sum,
  round(view_sum / num_uploads, 2) AS per_upload
SELECT
  uploader,
  count() AS num_uploads,
  formatReadableQuantity(view_sum) AS total_views,
  formatReadableQuantity(per_upload) AS views_per_video
FROM
  youtube
WHERE
  toYear(upload_date) = {year: UInt16}
GROUP BY uploader
ORDER BY per_upload desc
  LIMIT 10

Обратите внимание, что этот запрос содержит параметр (year), который выделен в примере выше. Параметры запроса можно задавать в формате { } вместе с типом параметра. Редактор запросов в консоли SQL автоматически распознает выражения параметров в запросах к ClickHouse и показывает отдельное поле ввода для каждого параметра.

Давайте быстро выполним этот запрос, чтобы убедиться, что он работает: укажите год 2010 в поле переменных запроса справа в редакторе SQL:

Проверка примера запроса

Затем сохраните запрос:

Сохранение примера запроса

Дополнительную информацию о сохраненных запросах можно найти в разделе "Saving a query".

Настройка эндпоинта Query API

Эндпоинты Query API можно настраивать прямо из представления запроса: нажмите кнопку Share и выберите API Endpoint. Затем вам будет предложено указать, какие ключ API смогут обращаться к этому эндпоинту Query API:

Настройка конечной точки запроса

После выбора ключа API вам будет предложено:

  • Выбрать роль базы данных, которая будет использоваться для выполнения запроса (Full access, Read only или Create a custom role)
  • Указать разрешенные домены CORS

После выбора этих параметров эндпоинт Query API будет создан автоматически.

Затем будет показан пример команды curl, чтобы вы могли отправить тестовый запрос:

Команда curl для конечной точки

Для удобства ниже приведена команда curl, отображаемая в интерфейсе:

curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow&param_year=<value>'

Параметры Query API

Параметры в запросе можно задавать с помощью синтаксиса {parameter_name: type}. Эти параметры будут автоматически обнаружены, а пример тела запроса будет содержать объект queryVariables, через который их можно передавать.

Тестирование и мониторинг

После создания эндпоинта Query API вы можете проверить его работу с помощью curl или любого другого HTTP-клиента:

тест curl для конечной точки

После отправки первого запроса сразу справа от кнопки Share должна появиться новая кнопка. При нажатии на нее откроется выдвижная панель с данными мониторинга по запросу:

Мониторинг конечной точки

Подробности реализации

Эта конечная точка выполняет запросы к вашим сохранённым эндпоинтам Query API. Она поддерживает несколько версий, гибкие форматы ответов, параметризованные запросы и опциональную потоковую передачу ответов (только в версии 2).

Конечная точка:

GET /query-endpoints/{queryEndpointId}/run
POST /query-endpoints/{queryEndpointId}/run

HTTP-методы

Метод Сценарий использования Параметры
GET Простые запросы с параметрами Передавайте переменные запроса через параметры URL (?param_name=value)
POST Сложные запросы или случаи, когда используется тело запроса Передавайте переменные запроса в теле запроса (объект queryVariables)

Когда использовать GET:

  • Простые запросы без сложных вложенных данных
  • Параметры легко передаются в URL-кодировке
  • Кэширование использует преимущества семантики HTTP GET

Когда использовать POST:

  • Сложные переменные запроса (массивы, объекты, длинные строки)
  • Когда тело запроса предпочтительнее с точки зрения безопасности и конфиденциальности
  • Потоковая загрузка файлов или больших объёмов данных

Аутентификация

Требуется: Да Метод: Basic Auth с помощью OpenAPI Key/Secret Разрешения: Соответствующие разрешения для эндпоинта запроса

Настройка запроса

Параметры URL

Параметр Обязательно Описание
queryEndpointId Да Уникальный идентификатор конечной точки запроса для выполнения

Параметры запроса

Параметр Обязательно Описание Пример
format Нет Формат ответа (поддерживаются все форматы ClickHouse) ?format=JSONEachRow
param_:name Нет Переменные запроса, если тело запроса передаётся как поток. Замените :name на имя своей переменной ?param_year=2024
request_timeout Нет Тайм-аут запроса в миллисекундах (по умолчанию: 30000) ?request_timeout=60000
:clickhouse_setting Нет Любая поддерживаемая настройка ClickHouse ?max_threads=8

Заголовки

Заголовок Обязательно Описание Значения
x-clickhouse-endpoint-version Нет Указывает версию конечной точки 1 или 2 (по умолчанию используется последняя сохранённая версия)
x-clickhouse-endpoint-upgrade Нет Инициирует обновление версии конечной точки (используйте вместе с заголовком версии) 1 для обновления

Тело запроса

Параметры

Параметр Тип Обязательный Описание
queryVariables объект Нет Переменные, используемые в запросе
format строка Нет Формат ответа

Поддерживаемые форматы

Версия Поддерживаемые форматы
Версия 2 Все форматы, поддерживаемые ClickHouse
Версия 1 (ограниченная поддержка) TabSeparated
TabSeparatedWithNames
TabSeparatedWithNamesAndTypes
JSON
JSONEachRow
CSV
CSVWithNames
CSVWithNamesAndTypes

Ответы

Успех

Статус: 200 OK Запрос успешно выполнен.

Коды ошибок

Код состояния Описание
400 Bad Request Запрос имеет неверный формат
401 Unauthorized Отсутствует аутентификация или недостаточно разрешений
404 Not Found Указанная конечная точка запроса не найдена

Рекомендации по обработке ошибок

  • Убедитесь, что запрос содержит действительные учетные данные для аутентификации
  • Проверьте queryEndpointId и queryVariables перед отправкой
  • Реализуйте корректную обработку ошибок с понятными сообщениями

Обновление версий конечных точек

Чтобы перейти с версии 1 на версию 2:

  1. Добавьте заголовок x-clickhouse-endpoint-upgrade со значением 1
  2. Добавьте заголовок x-clickhouse-endpoint-version со значением 2

Это дает доступ к возможностям версии 2, включая:

  • Поддержку всех форматов ClickHouse
  • Возможность потоковой передачи ответов
  • Более высокую производительность и расширенную функциональность

Примеры

Простой запрос

SQL для эндпоинта Query API:

SELECT database, name AS num_tables FROM system.tables LIMIT 3;

Версия 1

curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-d '{ "format": "JSONEachRow" }'

Версия 2

curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'
Ответapplication/x-ndjson
{"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
{"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
{"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}

Запрос с переменными запроса и версией 2 в формате JSONCompactEachRow

SQL для эндпоинта Query API:

SELECT name, database FROM system.tables WHERE match(name, {tableNameRegex: String}) AND database = {database: String};
curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONCompactEachRow&param_tableNameRegex=query.*&param_database=system' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'
Ответapplication/x-ndjson
["query_cache", "system"]
["query_log", "system"]
["query_views_log", "system"]

Запрос с массивом в параметрах запроса для вставки данных в таблицу

SQL таблицы:

CREATE TABLE default.t_arr
(
    `arr` Array(Array(Array(UInt32)))
)
ENGINE = MergeTree
ORDER BY tuple()

SQL для эндпоинта Query API:

INSERT INTO default.t_arr VALUES ({arr: Array(Array(Array(UInt32)))});
curl -X POST 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'Content-Type: application/json' \
-H 'x-clickhouse-endpoint-version: 2' \
-d '{
  "queryVariables": {
    "arr": [[[12, 13, 0, 1], [12]]]
  }
}'

Запрос с настройкой ClickHouse max_threads, равной 8

SQL для эндпоинта Query API:

SELECT * FROM system.tables;
curl 'https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?max_threads=8' \
--user '<openApiKeyId:openApiKeySecret>' \
-H 'x-clickhouse-endpoint-version: 2'

Запрос и разбор потокового ответа

SQL для эндпоинта Query API:

SELECT name, database FROM system.tables;
async function fetchAndLogChunks(
  url: string,
  openApiKeyId: string,
  openApiKeySecret: string
) {
  const auth = Buffer.from(`${openApiKeyId}:${openApiKeySecret}`).toString(
    "base64"
  );

  const headers = {
    Authorization: `Basic ${auth}`,
    "x-clickhouse-endpoint-version": "2",
  };

  const response = await fetch(url, {
    headers,
    method: "POST",
    body: JSON.stringify({ format: "JSONEachRow" }),
  });

  if (!response.ok) {
    console.error(`HTTP error! Status: ${response.status}`);
    return;
  }

  const reader = response.body as unknown as Readable;
  reader.on("data", (chunk) => {
    console.log(chunk.toString());
  });

  reader.on("end", () => {
    console.log("Stream ended.");
  });

  reader.on("error", (err) => {
    console.error("Stream error:", err);
  });
}

const endpointUrl =
  "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=JSONEachRow";
const openApiKeyId = "<myOpenApiKeyId>";
const openApiKeySecret = "<myOpenApiKeySecret>";
// Пример использования
fetchAndLogChunks(endpointUrl, openApiKeyId, openApiKeySecret).catch((err) =>
  console.error(err)
);
Выводshell
> npx tsx index.ts
> {"name":"COLUMNS","database":"INFORMATION_SCHEMA"}
> {"name":"KEY_COLUMN_USAGE","database":"INFORMATION_SCHEMA"}
...
> Stream ended.

Вставка потока из файла в таблицу

Создайте файл ./samples/my_first_table_2024-07-11.csv со следующим содержимым:

"user_id","json","name"
"1","{""name"":""John"",""age"":30}","John"
"2","{""name"":""Jane"",""age"":25}","Jane"

SQL-запрос CREATE TABLE:

create table default.my_first_table
(
    user_id String,
    json String,
    name String,
) ENGINE = MergeTree()
ORDER BY user_id;

SQL-код для эндпоинта Query API:

INSERT INTO default.my_first_table
cat ./samples/my_first_table_2024-07-11.csv | curl --user '<openApiKeyId:openApiKeySecret>' \
                                                   -X POST \
                                                   -H 'Content-Type: application/octet-stream' \
                                                   -H 'x-clickhouse-endpoint-version: 2' \
                                                   "https://console-api.clickhouse.cloud/.api/query-endpoints/<endpoint id>/run?format=CSV" \
                                                   --data-binary @-
Navigation