メインコンテンツへスキップ
メインコンテンツへスキップ

クエリ API エンドポイントの設定

Query API Endpoints 機能を使用すると、ClickHouse Cloud コンソールから任意の保存済み SQL クエリを元に、直接 API エンドポイントを作成できます。HTTP 経由で API エンドポイントにアクセスすることで、ネイティブドライバーを使って ClickHouse Cloud サービスに接続しなくても、保存済みクエリを実行できるようになります。

前提条件

次の項目を用意してから先に進んでください:

  • 適切な権限を持つ API キー
  • Admin Console ロール

まだ API キーを持っていない場合は、このガイドに従って API キーを作成 できます。

最低限必要な権限

API エンドポイントに対してクエリを実行するには、API キーに Member 組織ロールと Query Endpoints サービスアクセスが必要です。データベースロールはエンドポイントを作成するときに設定します。

保存済みクエリを作成する

既に保存済みクエリがある場合は、このステップをスキップできます。

新しいクエリタブを開きます。デモンストレーションとして、約 45 億レコードを含む youtube データセット を使用します。 "Create table" セクションの手順に従って、Cloud サービス上にテーブルを作成し、データを挿入してください。

ヒント
行数を LIMIT で制限する

このサンプルデータセットのチュートリアルでは 46.5 億行と非常に多くのデータを挿入するため、挿入に時間がかかる可能性があります。 このガイドの目的のためには、LIMIT 句を使用して、より少ないデータ量 (たとえば 1,000 万行) を挿入することを推奨します。

例として、ユーザーが入力する 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
-- highlight-next-line
  toYear(upload_date) = {year: UInt16}
GROUP BY uploader
ORDER BY per_upload desc
  LIMIT 10

このクエリには、上のスニペット内でハイライトされているパラメータ (year) が含まれている点に注意してください。 クエリパラメータは、パラメータの型とともに中かっこ { } を使って指定できます。 SQL コンソールのクエリエディタは ClickHouse のクエリパラメータ式を自動的に検出し、各パラメータに対応する入力欄を提供します。

SQL エディタ右側のクエリ変数入力ボックスで年に 2010 を指定し、このクエリをすばやく実行して動作を確認してみましょう:

サンプルクエリをテストする

次に、クエリを保存します:

サンプルクエリを保存する

保存済みクエリに関する詳細なドキュメントは "Saving a query" セクションにあります。

Query API エンドポイントの設定

クエリビューから、Share ボタンをクリックして API Endpoint を選択することで、Query API エンドポイントを直接設定できます。 どの API キーに対してエンドポイントへのアクセスを許可するか指定するよう求められます:

クエリエンドポイントを設定する

API キーを選択したら、次の内容を指定します:

  • クエリの実行に使用する Database ロール (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 メソッド

MethodUse CaseParameters
GETパラメータ付きのシンプルなクエリURL パラメータでクエリ変数を渡す(?param_name=value
POST複雑なクエリ、またはボディを利用する場合リクエストボディ内でクエリ変数を渡す(queryVariables オブジェクト)

GET を使用する場面:

  • 入れ子構造を含まないシンプルなクエリ
  • パラメータを容易に URL エンコードできる場合
  • HTTP GET のセマンティクスによるキャッシュの利点を活用したい場合

POST を使用する場面:

  • 配列、オブジェクト、大きな文字列などの複雑なクエリ変数
  • セキュリティ/プライバシー上、リクエストボディの利用が望ましい場合
  • ファイルのストリーミングアップロードや大容量データを送信する場合

認証

必須: Yes
方式: OpenAPI Key/Secret を用いた Basic 認証
権限: クエリエンドポイントに対して適切な権限が必要

リクエスト構成

URL パラメータ

ParameterRequiredDescription
queryEndpointIdYes実行するクエリエンドポイントの一意な識別子

クエリパラメータ

ParameterRequiredDescriptionExample
formatNoレスポンスフォーマット(すべての ClickHouse フォーマットをサポート)?format=JSONEachRow
param_:nameNoリクエストボディがストリームの場合のクエリ変数。:name を変数名に置き換える?param_year=2024
:clickhouse_settingNo任意のサポートされている ClickHouse setting?max_threads=8

ヘッダー

HeaderRequiredDescriptionValues
x-clickhouse-endpoint-versionNoエンドポイントのバージョンを指定1 または 2(デフォルトは最後に保存されたバージョン)
x-clickhouse-endpoint-upgradeNoエンドポイントのバージョンアップをトリガー(バージョンヘッダーと併用)1 を指定してアップグレード

リクエストボディ

パラメータ

ParameterTypeRequiredDescription
queryVariablesobjectNoクエリ内で使用する変数
formatstringNoレスポンスフォーマット

サポートされるフォーマット

VersionSupported Formats
Version 2ClickHouse がサポートするすべてのフォーマット
Version 1 (limited)TabSeparated
TabSeparatedWithNames
TabSeparatedWithNamesAndTypes
JSON
JSONEachRow
CSV
CSVWithNames
CSVWithNamesAndTypes

レスポンス

成功時

Status: 200 OK
クエリは正常に実行されました。

エラーコード

Status CodeDescription
400 Bad Requestリクエストの形式が不正
401 Unauthorized認証情報の欠如、または権限不足
404 Not Found指定されたクエリエンドポイントが存在しない

エラー処理のベストプラクティス

  • リクエストに有効な認証情報が含まれていることを確認する
  • 送信前に queryEndpointIdqueryVariables を検証する
  • 適切なエラーメッセージを含むグレースフルなエラー処理を実装する

エンドポイントバージョンのアップグレード

Version 1 から Version 2 にアップグレードするには:

  1. x-clickhouse-endpoint-upgrade ヘッダーを 1 に設定して含める
  2. x-clickhouse-endpoint-version ヘッダーを 2 に設定して含める

これにより、以下を含む 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"}

クエリ変数とバージョン2を使用したJSONCompactEachRow形式のリクエスト

クエリ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'

ストリームとしてレスポンスをリクエストして解析する

クエリ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>"
// Usage example
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.

ファイルからテーブルへストリームを挿入する

以下の内容で ./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 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 @-