跳转到主要内容
查询 API 端点功能允许您直接根据 ClickHouse Cloud 控制台中任意已保存的 SQL 查询创建 API 端点。您可以通过 HTTP 访问这些 API 端点来执行已保存的查询,而无需使用原生驱动程序连接到您的 ClickHouse Cloud 服务。

前提条件

继续之前,请确保你具备:
  • 具有相应权限的 API 密钥
  • Admin Console 角色
如果你还没有 API 密钥,可以按照本指南创建 API 密钥
最低权限要查询 API 端点,API 密钥需要具备 Member 组织角色以及 Query Endpoints 服务访问权限。数据库角色会在你创建端点时配置。
1

创建已保存的查询

如果你已经有已保存的查询,可以跳过此步骤。打开一个新的查询标签页。为了演示,我们将使用 youtube dataset,其中包含大约 45 亿条记录。 按照 “Create table” 部分中的步骤,在你的 Cloud 服务上创建该表并向其中插入数据。
使用 LIMIT 限制行数示例数据集教程会插入大量数据——46.5 亿行,因此插入可能需要一些时间。 为便于完成本指南,我们建议使用 LIMIT 子句插入较少的数据, 例如 1000 万行。
作为示例查询,我们将返回用户输入的 year 参数对应年份中,按每个视频平均观看次数排序的前 10 位上传者。
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 查询参数表达式,并为每个参数提供一个输入框。现在快速运行这个查询,在 SQL 编辑器右侧的查询变量输入框中指定年份 2010,确认它能够正常工作:接下来,保存该查询:有关已保存查询的更多文档,请参阅 “Saving a query” 部分。
2

配置查询 API 端点

可以直接在查询视图中点击 共享 按钮并选择 API Endpoint 来配置查询 API 端点。 系统会提示你指定哪些 API 密钥可以访问该端点:选择 API 密钥后,系统会要求你:
  • 选择用于运行该查询的数据库角色 (Full accessRead onlyCreate a custom role)
  • 指定允许跨源资源共享 (CORS) 的域名
选择这些选项后,查询 API 端点将自动完成配置。界面中会显示一个示例 curl 命令,便于你发送测试请求:为方便起见,界面中显示的 curl 命令如下:
curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow&param_year=<value>'
3

查询 API 参数

查询参数可使用 {parameter_name: type} 语法来指定。系统会自动检测这些参数,示例请求载荷中将包含一个 queryVariables 对象,你可以通过它传递这些参数。
4

测试与监控

创建查询 API 端点后,你可以使用 curl 或任何其他 HTTP 客户端测试其是否正常工作:发送第一个请求后,共享 按钮右侧应会立即出现一个新按钮。点击它会打开一个弹出面板,其中包含该查询的监控数据:

实现细节

此端点用于执行您已保存的查询 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:
  • 复杂的查询变量 (数组、对象、长字符串)
  • 出于安全或隐私考虑,优先使用请求体时
  • 流式文件上传或大体量数据

身份验证

必需:方法: 使用 OpenAPI Key/Secret 进行 Basic Auth 身份验证 权限: 访问查询端点所需的相应权限

请求配置

URL 参数

参数必填描述
queryEndpointId要执行的查询端点的唯一标识符

查询参数

参数必填描述示例
format响应格式 (支持所有 ClickHouse 格式)?format=JSONEachRow
param_:name当请求体为 stream 时使用的查询变量。请将 :name 替换为你的变量名?param_year=2024
request_timeout查询超时时间 (单位为毫秒,默认值:30000)?request_timeout=60000
:clickhouse_setting任意受支持的 ClickHouse 设置?max_threads=8

请求头

请求头必需描述
x-clickhouse-endpoint-version指定端点版本12 (默认为最近一次保存的版本)
x-clickhouse-endpoint-upgrade触发端点版本升级 (与版本请求头一起使用)1 表示升级

请求体

参数

参数类型必填描述
queryVariablesobject查询中使用的变量
formatstring返回格式

支持的格式

版本支持的格式
版本 2ClickHouse 支持的所有格式
版本 1 (受限) TabSeparated
TabSeparatedWithNames
TabSeparatedWithNamesAndTypes
JSON
JSONEachRow
CSV
CSVWithNames
CSVWithNamesAndTypes

返回结果

成功

状态: 200 OK 查询已成功执行。

错误码

状态码说明
400 Bad Request请求格式有误
401 Unauthorized缺少身份验证或权限不足
404 Not Found未找到指定的查询端点

错误处理最佳实践

  • 确保请求中包含有效的身份验证凭据
  • 在发送前先验证 queryEndpointIdqueryVariables
  • 妥善处理错误,并提供恰当的错误消息

升级端点版本

要从版本 1 升级到版本 2:
  1. 添加值为 1x-clickhouse-endpoint-upgrade 请求头
  2. 添加值为 2x-clickhouse-endpoint-version 请求头
这样即可使用版本 2 的功能,包括:
  • 支持所有 ClickHouse 格式
  • 支持响应流式传输
  • 提升的性能和功能

示例

基本请求

查询 API 端点 SQL:
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'
响应
{"database":"INFORMATION_SCHEMA","num_tables":"COLUMNS"}
{"database":"INFORMATION_SCHEMA","num_tables":"KEY_COLUMN_USAGE"}
{"database":"INFORMATION_SCHEMA","num_tables":"REFERENTIAL_CONSTRAINTS"}

使用查询变量和 JSONCompactEachRow 格式版本 2 发起请求

查询 API 端点 SQL:
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'
响应
["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()
查询 API 端点 SQL:
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 的请求

查询 API 端点 SQL:
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'

请求并将响应作为stream解析`

查询 API 端点 SQL:
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)
);
输出
> npx tsx index.ts
> {"name":"COLUMNS","database":"INFORMATION_SCHEMA"}
> {"name":"KEY_COLUMN_USAGE","database":"INFORMATION_SCHEMA"}
...
> Stream ended.

将文件中的stream插入表中

创建文件 ./samples/my_first_table_2024-07-11.csv,内容如下:
"user_id","json","name"
"1","{""name"":""John"",""age"":30}","John"
"2","{""name"":""Jane"",""age"":25}","Jane"
CREATE TABLE SQL:
create table default.my_first_table
(
    user_id String,
    json String,
    name String,
) ENGINE = MergeTree()
ORDER BY user_id;
查询 API 端点 SQL:
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 @-
最后修改于 2026年6月10日