ClickHouse Go
シンプルな例
シンプルな例を見ていきましょう。これによりClickHouseに接続し、システムデータベースから選択します。始めるには、接続の詳細が必要です。
接続の詳細
ClickHouseにネイティブTCPで接続するには、以下の情報が必要です:
-
HOSTとPORT:通常、TLSを使用する場合はポートが9440、TLSを使用しない場合は9000です。
-
DATABASE NAME:デフォルトでは
default
というデータベースが存在します。接続したいデータベースの名前を使用してください。 -
USERNAMEとPASSWORD:デフォルトではユーザー名が
default
です。使用ケースに応じたユーザー名を使用してください。
ClickHouse Cloudサービスの詳細は、ClickHouse Cloudコンソールで確認できます。接続するサービスを選択し、Connectをクリックしてください:

Nativeを選択すると、例のclickhouse-client
コマンドで詳細が確認できます。

セルフマネージドのClickHouseを使用している場合は、接続の詳細はClickHouse管理者によって設定されます。
モジュールの初期化
サンプルコードのコピー
このコードを clickhouse-golang-example
ディレクトリに main.go
としてコピーします。
go mod tidyの実行
接続の詳細を設定
以前に接続の詳細を調べました。それらを main.go
の connect()
関数に設定してください:
例を実行
さらに学ぶ
このカテゴリの残りのドキュメントでは、ClickHouse Goクライアントの詳細について説明しています。
ClickHouse Goクライアント
ClickHouseは2つの公式Goクライアントをサポートしています。これらのクライアントは補完的であり、意図的に異なるユースケースをサポートしています。
- clickhouse-go - Go標準database/sqlインターフェースまたはネイティブインターフェースのいずれかをサポートする高レベル言語クライアント。
- ch-go - 低レベルクライアント。ネイティブインターフェースのみ。
clickhouse-goは高レベルインターフェースを提供し、データ型に対して寛容な行指向のセマンティクスとバッチを使用してデータをクエリおよび挿入できます。ch-goは一方で、型の厳格さと複雑な使用法の代償として、低CPUおよびメモリオーバーヘッドで高速なデータブロックストリーミングを提供する最適化された列指向インターフェースを提供します。
バージョン2.3から、clickhouse-goはエンコーディング、デコーディング、圧縮などの低レベル機能にch-goを利用しています。なお、clickhouse-goはGoのdatabase/sql
インターフェース標準もサポートしています。両方のクライアントはネイティブ形式を使用してエンコーディングを行い、最適なパフォーマンスを提供し、ネイティブClickHouseプロトコルを介して通信できます。また、clickhouse-goは、ユーザーがトラフィックをプロキシまたは負荷分散する必要がある場合のためにHTTPもトランスポートメカニズムとしてサポートしています。
クライアントライブラリを選択する際には、それぞれの利点と欠点を理解しておく必要があります - クライアントライブラリの選択を見てください。
ネイティブ形式 | ネイティブプロトコル | HTTPプロトコル | 行指向API | 列指向API | 型の柔軟性 | 圧縮 | クエリプレースホルダ | |
---|---|---|---|---|---|---|---|---|
clickhouse-go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
ch-go | ✅ | ✅ | ✅ | ✅ |
クライアントの選択
クライアントライブラリの選択は、使用パターンと最適なパフォーマンスの必要性に依存します。毎秒数百万の挿入が要求される挿入重視のユースケースでは、低レベルクライアント ch-go を使用することをお勧めします。このクライアントは、ClickHouseのネイティブ形式が要求する行指向形式から列へのデータピボットに関連するオーバーヘッドを回避します。さらに、interface{}
(any
) 型の反射や使用を避けて、使用を簡単にしています。
集計に重点を置いたクエリワークロードやスループットが低い挿入ワークロードの場合、clickhouse-go が馴染みのある database/sql
インターフェースとより簡潔な行セマンティクスを提供します。ユーザーは、トランスポートプロトコルとしてHTTPを選択的に使用し、行を構造体に変換するためのヘルパー関数を利用できる場合もあります。
clickhouse-goクライアント
clickhouse-goクライアントはClickHouseとの通信のために2つのAPIインターフェースを提供します:
- ClickHouseクライアント特有のAPI
database/sql
標準 - Golangが提供するSQLデータベースの一般的なインターフェース。
database/sql
はデータベースに依存しないインターフェースを提供し、デベロッパーがデータストアを抽象化できるようにしますが、一部の型とクエリセマンティクスを強制し、パフォーマンスに影響を与えます。このため、パフォーマンスが重要な場合 はクライアント特有のAPIを使用するべきです。しかし、複数のデータベースをサポートするツールにClickHouseを統合したいユーザーは、標準インターフェースを使用することを好むかもしれません。
両方のインターフェースはネイティブ形式とネイティブプロトコルを使用してデータをエンコードします。また、標準インターフェースはHTTPを介した通信もサポートしています。
ネイティブ形式 | ネイティブプロトコル | HTTPプロトコル | 一括書き込みサポート | 構造体マシュアル | 圧縮 | クエリプレースホルダ | |
---|---|---|---|---|---|---|---|
ClickHouse API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
database/sql API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
インストール
ドライバーのv1は非推奨であり、機能更新や新しいClickHouseタイプのサポートは行われません。ユーザーは性能が優れているv2に移行するべきです。
クライアントの2.xバージョンをインストールするには、go.modファイルにパッケージを追加します:
require github.com/ClickHouse/clickhouse-go/v2 main
または、リポジトリをクローンします:
別のバージョンをインストールするには、パスまたはブランチ名を適宜修正してください。
バージョン管理と互換性
クライアントはClickHouseとは独立してリリースされます。2.xは現在開発中の主要バージョンを表します。すべての2.xバージョンは互換性があります。
ClickHouse互換性
クライアントは以下をサポートします:
- すべての現在サポートされているClickHouseバージョン こちら に記録されています。ClickHouseのバージョンがサポートされなくなった場合、それらはクライアントリリースに対しても積極的にはテストされなくなります。
- クライアントのリリース日から2年間、すべてのClickHouseバージョン。なお、LTSバージョンのみ積極的にテストされます。
Golang互換性
クライアントバージョン | Golangバージョン |
---|---|
=> 2.0 <= 2.2 | 1.17, 1.18 |
>= 2.3 | 1.18 |
ClickHouseクライアントAPI
ClickHouseクライアントAPIのすべてのコードサンプルは こちら で見つけることができます。
接続
以下の例は、サーバーバージョンを返し、ClickHouseに接続することを示しており、ClickHouseが保護されていないことを前提とし、デフォルトユーザーでアクセスできます。
デフォルトのネイティブポートを使用して接続します。
すべてのその後の例では、明示的に示されない限り、ClickHouse conn
変数が作成され、利用可能であることを前提とします。
接続設定
接続を開くときは、Options構造体を使用してクライアントの動作を制御できます。利用可能な設定は次のとおりです:
Protocol
- ネイティブまたはHTTP。HTTPは、現在database/sql APIのみに対応しています。TLS
- TLSオプション。非nilの値はTLSを有効にします。TLSの使用を参照してください。Addr
- ポートを含むアドレスのスライス。Auth
- 認証の詳細。認証を参照してください。DialContext
- 接続を確立する方法を決定するカスタムダイヤル関数。Debug
- デバッグを有効にするためのtrue/false。Debugf
- デバッグ出力を消費する関数を提供します。debug
をtrueに設定する必要があります。Settings
- ClickHouse設定のマップ。これらはすべてのClickHouseクエリに適用されます。コンテキストの使用によりクエリごとに設定を設定できます。Compression
- ブロックの圧縮を有効にします。圧縮を参照してください。DialTimeout
- 接続を確立する最大時間。デフォルトは1s
。MaxOpenConns
- いつでも使用できる最大接続数。アイドルプールにはそれ以上またはそれ以下の接続があるかもしれませんが、いつでもこの数の接続しか使用できません。デフォルトはMaxIdleConns+5
。MaxIdleConns
- プール内で維持する接続の数。可能な場合、接続は再利用されます。デフォルトは5
。ConnMaxLifetime
- 接続を使用可能な状態で保持する最大期間。デフォルトは1時間。接続はこの時間が経過すると破棄され、新しい接続が必要に応じてプールに追加されます。ConnOpenStrategy
- ノードアドレスのリストをどのように消費し、使用して接続を開くかを決定します。複数ノードへの接続を参照してください。BlockBufferSize
- 一度にバッファにデコードするブロックの最大数。大きな値はメモリの代償で並列化を増加させます。ブロックサイズはクエリに依存するため、接続時にこれを設定できますが、返すデータに基づいてクエリごとに上書きすることをお勧めします。デフォルトは2
。
接続プーリング
クライアントは接続プールを維持し、必要に応じてこれをクエリに再利用します。最大で、MaxOpenConns
がいつでも使用され、プールの最大サイズは MaxIdleConns
によって制御されます。クライアントは各クエリ実行のためにプールから接続を取得し、再利用のためにプールに返します。接続はバッチの寿命に使用され、Send()
で解放されます。
プール内の同じ接続がその後のクエリで使用されることは保証されていません。もしユーザーが MaxOpenConns=1
を設定しない限り。これは通常必要とされることはありませんが、ユーザーが一時テーブルを使用している場合には必要になることがあります。
また、ConnMaxLifetime
はデフォルトで1時間です。これは、ノードがクラスタから離れた場合にClickHouseへの負荷が不均衡になるケースを引き起こす可能性があります。ノードが利用できなくなると、この接続は他のノードにバランスされます。これらの接続は保持され、デフォルトで1時間はリフレッシュされません。問題のあるノードがクラスタに戻ってもそうです。重いワークロードの場合はこの値を下げることを検討してください。
TLSの使用
低レベルでは、すべてのクライアント接続メソッド(DSN/OpenDB/Open
)は、Go tlsパッケージを使用して安全な接続を確立します。Options構造体に非nilの tls.Config
ポインタが含まれている場合、クライアントはTLSを使用することを知っています。
この最小限の TLS.Config
は通常、ClickHouseサーバーのセキュアネイティブポート(通常9440)に接続するために十分です。ClickHouseサーバーに有効な証明書(期限切れ、誤ったホスト名、公開認識されたルート認証局によって署名されていない)がない場合、InsecureSkipVerify
をtrueにすることができますが、これは強く推奨されません。
追加のTLSパラメータが必要な場合、アプリケーションコードはtls.Config
構造体内の希望するフィールドを設定する必要があります。これには、特定の暗号スイートの強制、特定のTLSバージョン(1.2や1.3など)の強制、内部CA証明書チェーンの追加、ClickHouseサーバーによって必要とされる場合にクライアント証明書(および秘密鍵)の追加、その他の専門的なセキュリティ設定に関するすべてのオプションが含まれます。
認証
接続の詳細にAuth構造体を指定して、ユーザー名とパスワードを指定します。
複数ノードへの接続
複数のアドレスを Addr
構造体を介して指定できます。
2つの接続戦略が利用可能です:
ConnOpenInOrder
(デフォルト) - アドレスは順に消費されます。後のアドレスは、リストの先頭にあるアドレスを使用して接続できない場合にのみ利用されます。これは事実上のフェイルオーバー戦略です。ConnOpenRoundRobin
- ロードがラウンドロビン戦略を使用してアドレス間でバランスが取られます。
これはオプション ConnOpenStrategy
を介して制御できます。
実行
任意のステートメントは Exec
メソッドを介して実行できます。これはDDLおよびシンプルなステートメントに便利です。大きな挿入やクエリの反復には使用すべきではありません。
クエリにコンテキストを渡す能力に注意してください。これは特定のクエリレベル設定を渡すために使用できます - コンテキストの使用を参照してください。
バッチ挿入
多数の行を挿入するには、クライアントはバッチセマンティクスを提供します。これにより、行を追加できるようにバッチを準備する必要があります。これは最終的に Send()
メソッドを介して送信されます。バッチはSendが実行されるまでメモリに保持されます。
ClickHouseの推奨事項がここにも適用されます。バッチはゴルーチン間で共有するべきではなく、各ゴルーチンごとに別々のバッチを構築する必要があります。
上記の例から、行を追加する際には変数タイプがカラムタイプと一致する必要があることに注意してください。マッピングが通常は明白である一方で、このインターフェースは柔軟性を持つようにし、精度損失が生じない限り型を変換します。たとえば、以下はdatetime64に文字列を挿入するデモです。
各カラムタイプのサポートされているgo型の完全な概要は、型変換を参照してください。
行のクエリ
ユーザーは QueryRow
メソッドを使用して単一の行をクエリするか、Query
を介して結果セットを反復するためのカーソルを取得できます。前者はデータをシリアライズするための宛先を受け入れ、後者は各行で Scan
を呼び出す必要があります。
この場合、我々はそれぞれのカラム値をシリアライズするためにポインタを渡す必要があります。これらは SELECT
ステートメントで指定された順序で渡す必要があり、デフォルトでは SELECT *
の場合カラム宣言の順序が使用されます。
挿入時と同様に、Scanメソッドはターゲット変数が適切な型である必要があります。このインターフェースは柔軟性を持つことを目指しており、精度損失がない場合は可能な限り型を変換します。たとえば、上記の例は、UUIDカラムが文字列変数に読み込まれることを示しています。サポートされているgo型の完全なリストは、各カラムタイプの型変換を参照してください。
最後に、Query
と QueryRow
メソッドに Context
を渡す能力に注意してください。これはクエリレベルの設定に使用できます - コンテキストの使用の詳細を確認してください。
非同期挿入
非同期挿入はAsyncメソッドを介してサポートされています。これにより、クライアントがサーバーが挿入を完了するまで待機するか、データが受信された時点で応答するかを指定できます。これは事実上 wait_for_async_insert パラメータを制御します。
列指向の挿入
挿入は列形式で挿入できます。これにより、データがすでにこの構造で配置されている場合にパフォーマンス上の利点が得られ、行にピボットする必要がなくなります。
構造体の使用
ユーザーにとって、Golangの構造体はClickHouseのデータ行を論理的に表現します。これを支援するために、ネイティブインターフェースはいくつかの便利な関数を提供します。
シリアライズを伴う選択
Selectメソッドは、応答行のセットを単一の呼び出しで構造体のスライスにマシュアルします。
構造体をスキャンする
ScanStruct
は、クエリからの単一の行を構造体にマシュアルすることを可能にします。
型変換
クライアントは、挿入とレスポンスのマーシャリングの双方に対し、変数型を受け入れる柔軟性を持つことを目指しています。ほとんどの場合、ClickHouse カラム型に対する同等の Golang 型が存在し、例えば、 UInt64 は uint64 に対応しています。これらの論理マッピングは常にサポートされるべきです。ユーザーは、挿入できるカラムに対して、またはレスポンスを受け取るために、どちらかの変数や受信データの変換が最初に行われる場合に変数型を使用したいと考えるかもしれません。クライアントは、これらの変換を透明にサポートし、ユーザーがデータを正確に揃えるために変換する必要がなく、クエリ時で柔軟なマーシャリングを提供できるようにします。この透明な変換は、精度の損失を許可しません。たとえば、uint32 は UInt64 カラムからデータを受け取るためには使用できません。逆に、時間の形式要件を満たす場合、文字列は datetime64 フィールドに挿入できます。
現在サポートされている原始型の型変換は こちら に記載されています。
この取り組みは継続中であり、挿入(Append
/AppendRow
)とリードタイム(Scan
を介して)に分けることができます。特定の変換に対するサポートが必要な場合は、問題を提起してください。
複合型
日付/日時型
ClickHouse の Go クライアントは、Date
、Date32
、DateTime
、および DateTime64
の日付/日時型をサポートしています。日付は 2006-01-02
形式の文字列として挿入するか、ネイティブ Go の time.Time{}
または sql.NullTime
を使用できます。日時は後者の型もサポートしていますが、文字列は 2006-01-02 15:04:05
形式で渡す必要があり、オプションのタイムゾーンオフセット(例:2006-01-02 15:04:05 +08:00
)が必要です。time.Time{}
と sql.NullTime
は、リードタイムでもサポートされており、sql.Scanner
インターフェースの実装であればどれでも対応します。
タイムゾーン情報の取り扱いは、ClickHouse 型や、値が挿入されているか読み取られているかによって異なります:
- DateTime/DateTime64
- 挿入時、値は UNIX タイムスタンプ形式で ClickHouse に送信されます。タイムゾーンが指定されていない場合、クライアントはクライアントのローカルタイムゾーンを仮定します。
time.Time{}
またはsql.NullTime
は適宜エポックに変換されます。 - 選択時、カラムのタイムゾーンが設定されている場合はそれが使用されて
time.Time
値が返されます。設定されていない場合は、サーバーのタイムゾーンが使用されます。
- 挿入時、値は UNIX タイムスタンプ形式で ClickHouse に送信されます。タイムゾーンが指定されていない場合、クライアントはクライアントのローカルタイムゾーンを仮定します。
- Date/Date32
- 挿入時、Unix タイムスタンプに変換するときにタイムゾーンが考慮され、データが日付として保存される前にタイムゾーンでオフセットされます。ClickHouse では Date 型にはロケールがないため、文字列値でこれが指定されていない場合はローカルタイムゾーンが使用されます。
- 選択時、日付は
time.Time{}
またはsql.NullTime{}
インスタンスにスキャンされ、タイムゾーン情報は返されません。
配列
配列はスライスとして挿入する必要があります。要素の型付けルールは 原始型 に関するものと一貫しており、可能な場合には要素が変換されます。
スキャン時には、スライスへのポインタを指定する必要があります。
マップ
マップは、型ルールに準拠したキーと値を持つ Golang マップとして挿入されるべきです。
タプル
タプルは、任意の長さのカラムのグループを表します。カラムは明示的に名前付けされることも、単に型を指定することもできます。例えば:
これらのアプローチの中で、名前付きタプルはより柔軟性を提供します。名前なしのタプルはスライスを使用して挿入および読み取りする必要がありますが、名前付きタプルはマップとも互換性があります。
注意:型付けされたスライスおよびマップがサポートされている場合は、名前付きタプルのサブカラムすべてが同じ型である必要があります。
ネスト
ネストされたフィールドは、名前付きタプルの配列に相当します。使用は、ユーザーが flatten_nested を 1 または 0 に設定したかどうかに依存します。
flatten_nested
を 0 に設定すると、ネストされたカラムは単一のタプルの配列として維持されます。これにより、ユーザーは挿入と取得のためにマップのスライスを使用し、任意のネストレベルを持つことができます。マップのキーはカラムの名前と等しくする必要があります。以下の例に示すように。
注意:マップはタプルを表すため、map[string]interface{}
型である必要があります。現在、値は強く型付けされていません。
flatten_nested
のデフォルト値である 1 が使用されると、ネストされたカラムは別々の配列にフラット化されます。これには、挿入と取得のためにネストされたスライスを使用する必要があります。任意のネストレベルが機能する場合もありますが、これは公式にはサポートされていません。
注意:ネストされたカラムは同じ次元である必要があります。たとえば、上記の例では、 Col_2_2
と Col_2_1
は同じ数の要素を持つ必要があります。
よりシンプルなインターフェースとネスティングに対する公式なサポートのために、flatten_nested=0
を推奨します。
ジオタイプ
クライアントは、ジオタイプである Point、Ring、Polygon、および Multi Polygon をサポートしています。これらのフィールドは Golang で、github.com/paulmach/orb パッケージを使用して扱われます。
UUID
UUID 型は github.com/google/uuid パッケージによってサポートされています。ユーザーは UUID を文字列として送信およびマーシャリングすることも、sql.Scanner
または Stringify
を実装している任意の型として扱うこともできます。
Decimal
Decimal 型は github.com/shopspring/decimal パッケージによってサポートされています。
Nullable
Go の Nil 値は、ClickHouse の NULL を表します。これは、フィールドが Nullable として宣言されている場合に使用できます。挿入時には、通常のカラムと Nullable バージョンの両方に対して Nil を渡すことができます。前者の場合は、その型のデフォルト値が保持され、例えば文字列の場合は空の文字列になります。Nullable バージョンの場合は、ClickHouse に NULL 値が保存されます。
スキャン時には、ユーザーは nil をサポートする型(例えば *string)へのポインタを渡さなくてはなりません。これにより、Nullable フィールドについての nil 値が表現されます。以下の例では、col1 が Nullable(String) のため、**string を受け取ります。これにより nil が表現可能となります。
クライアントはさらに sql.Null*
型(例:sql.NullInt64
)もサポートしています。これらは、それぞれの同等の ClickHouse 型と互換性があります。
ビッグイント - Int128, Int256, UInt128, UInt256
64 ビットを超える数値型は、ネイティブ Go の big パッケージを使用して表示されます。
圧縮
圧縮メソッドのサポートは、使用するプロトコルに依存します。ネイティブプロトコルの場合、クライアントは LZ4
および ZSTD
圧縮をサポートしています。これはブロックレベルでのみ実行されます。圧縮は接続に Compression
設定を含めることで有効にできます。
標準インターフェースを通じて HTTP を使用する場合に、追加の圧縮技術が利用可能です。詳細については database/sql API - 圧縮 を参照してください。
パラメータバインディング
クライアントは、Exec
、Query
、および QueryRow
メソッドのためのパラメータバインディングをサポートしています。以下の例に示すように、これは名前付き、番号付き、および位置指定のパラメータを使用してサポートされています。これらの例を以下に示します。
特殊なケース
デフォルトでは、スライスはクエリにパラメータとして渡された場合、カンマで区切られた値のリストに展開されます。ユーザーが、値のセットを [ ]
でラッピングして挿入する必要がある場合、ArraySet
を使用する必要があります。
グループやタプルが必要な場合は、 IN
演算子で使用するために、 GroupSet
を使用できます。これは、複数のグループが必要な場合に特に便利で、以下の例に示されています。
最後に、DateTime64 フィールドは、パラメータが適切に描画されるように精度が要求されます。しかし、フィールドの精度レベルはクライアントによって不明であるため、ユーザーがそれを提供する必要があります。そのため、DateNamed
パラメータを提供しています。
コンテキストの使用
Go のコンテキストは、期限、キャンセルシグナル、および他のリクエストスコープ値を API 境界を越えて渡す手段を提供します。接続のすべてのメソッドは、最初の変数としてコンテキストを受け取ります。前の例では context.Background() を使用しましたが、ユーザーはこの機能を利用して設定や期限を渡し、クエリをキャンセルすることができます。
withDeadline
で作成されたコンテキストを渡すことで、クエリに対して実行時間制限を設定することができます。これは絶対的な時間であり、期限が過ぎると接続が解放され、ClickHouse にキャンセルシグナルが送信されます。 alternatively, WithCancel
を使用して、クエリを明示的にキャンセルすることもできます。
ヘルパーである clickhouse.WithQueryID
および clickhouse.WithQuotaKey
を使用することで、クエリ ID およびクオータキーを指定できます。クエリ ID は、ログ内でクエリを追跡し、キャンセルを目的として便利です。クオータキーは、ユニークキー値に基づいて ClickHouse の使用制限を課すために使用できます - 詳細は クオータ管理 を参照してください。
ユーザーはまた、特定のクエリにのみ設定を適用するためにコンテキストを使用できます - 接続全体ではなく、接続設定に示したように。
最後に、ユーザーは clickhouse.WithBlockSize
を介してブロックバッファのサイズを制御できます。これにより、接続レベル設定 BlockBufferSize
がオーバーライドされ、メモリ内にデコードされ保持されるブロックの最大数が制御されます。大きな値は、メモリを犠牲にして並列処理が増加する可能性があります。
上記の例は、以下に示されています。
進捗/プロファイル/ログ情報
クエリに対して進捗、プロファイル、ログ情報をリクエストすることができます。進捗情報は、ClickHouseで読み取りおよび処理された行数とバイト数に関する統計を報告します。一方、プロファイル情報は、クライアントに返されたデータの概要を提供し、バイトの合計(圧縮されていない)、行数、ブロック数を含みます。最後に、ログ情報は、スレッドに関する統計(例:メモリ使用量やデータ速度)を提供します。
この情報を取得するには、ユーザーがContextを使用する必要があり、ユーザーはコールバック関数を渡すことができます。
動的スキャン
ユーザーは、スキーマや返されるフィールドの型が不明なテーブルを読み取る必要がある場合があります。これは、アドホックデータ分析が行われる場合や汎用ツールが書かれる場合によく見られます。これを実現するために、クエリレスポンスにはカラムタイプ情報が提供されます。これをGoのリフレクションと組み合わせて、正しい型の変数のランタイムインスタンスを作成し、Scanに渡すことができます。
外部テーブル
外部テーブルは、クライアントがSELECTクエリを使用してClickHouseにデータを送信できるようにします。このデータは一時テーブルに置かれ、クエリ自体で評価に使用できます。
クエリを使用してクライアントに外部データを送信するには、ユーザーはコンテキストを介してこれを渡す前にext.NewTable
を使用して外部テーブルを構築する必要があります。
OpenTelemetry
ClickHouseは、ネイティブプロトコルの一部としてトレースコンテキストを渡すことを許可します。クライアントは、clickhouse.withSpan
関数を介してSpanを作成し、これをContextを介して渡すことができます。
トレースを活用するための詳細は、OpenTelemetryサポートに記載されています。
データベース/SQL API
database/sql
または「標準」APIは、アプリケーションコードが基盤となるデータベースに無関心であるべきシナリオでクライアントを使用できるようにします。これはいくつかのコストを伴います - 追加の抽象化層、間接的であり、ClickHouseと必ずしも一致しないプリミティブが含まれます。しかし、これらのコストは、ツールが複数のデータベースに接続する必要があるシナリオでは通常受け入れられます。
さらに、このクライアントはHTTPを輸送層として使用することもサポートしており、データは最適なパフォーマンスのためにネイティブフォーマットでエンコードされます。
以下は、ClickHouse APIのドキュメントの構造を反映することを目指しています。
標準APIの完全なコード例は、ここで見つけることができます。
接続
接続は、形式clickhouse://<host>:<port>?<query_option>=<value>
のDSN文字列またはclickhouse.OpenDB
メソッドを介して達成できます。後者はdatabase/sql
の仕様の一部ではありませんが、sql.DB
インスタンスを返します。このメソッドは、database/sql
の仕様を通じて明示的に公開する手段がないプロファイリングなどの機能を提供します。
以降のすべての例では、明示的に表示されない限り、ClickHouse conn
変数が作成されているものと仮定します。
接続設定
次のパラメータをDSN文字列に渡すことができます:
hosts
- ロードバランシングとフェイルオーバーのための単一のアドレスホストのカンマ区切りリスト - 複数ノードへの接続を参照してください。username/password
- 認証情報 - 認証を参照してください。database
- 現在のデフォルトデータベースを選択します。dial_timeout
- 期間文字列は、符号付きの10進数の数列であり、オプションの分数と単位接尾辞を持ちます(例:300ms
、1s
)。有効な時間単位はms
、s
、m
です。connection_open_strategy
-random/in_order
(デフォルトはrandom
) - 複数ノードへの接続を参照してください。round_robin
- セットからラウンドロビンサーバーを選択します。in_order
- 指定された順序で最初のライブサーバーが選択されます。
debug
- デバッグ出力を有効にします(ブール値)。compress
- 圧縮アルゴリズムを指定します -none
(デフォルト)、zstd
、lz4
、gzip
、deflate
、br
。true
に設定すると、lz4
が使用されます。ネイティブ通信ではlz4
とzstd
のみがサポートされています。compress_level
- 圧縮レベル(デフォルトは0
)。圧縮を参照してください。これはアルゴリズムによって特異です:gzip
--2
(最良の速度)から9
(最良の圧縮)deflate
--2
(最良の速度)から9
(最良の圧縮)br
-0
(最良の速度)から11
(最良の圧縮)zstd
、lz4
- 無視されます。
secure
- 安全なSSL接続を確立します(デフォルトはfalse
)。skip_verify
- 証明書検証をスキップします(デフォルトはfalse
)。block_buffer_size
- ユーザーがブロックバッファサイズを制御できるようにします。BlockBufferSize
を参照してください。(デフォルトは2
)
接続プーリング
ユーザーは、複数ノードへの接続で説明したように、提供されたノードアドレスのリストの使用に影響を与えることができます。ただし、接続管理とプーリングは設計上sql.DB
に委任されます。
HTTP経由での接続
デフォルトでは、接続はネイティブプロトコルを介して確立されます。HTTPが必要なユーザーは、DSNを修正してHTTPプロトコルを含めるか、接続オプションでプロトコルを指定することでこれを有効にできます。
複数ノードへの接続
OpenDB
を使用する場合、ClickHouse APIに使用されるのと同じオプションアプローチを使用して、同じオプションセットを使用して複数のホストに接続します - ConnOpenStrategy
を指定することもできます。
DSNベースの接続では、文字列は複数のホストとconnection_open_strategy
パラメータを受け入れ、round_robin
またはin_order
の値を設定できます。
TLSを使用する
DSN接続文字列を使用している場合、SSLは"secure=true"パラメータを介して有効にできます。OpenDB
メソッドは、非nil TLS構造体の指定に依存しており、TLS用のネイティブAPIと同じアプローチを利用します。DSN接続文字列はSSL検証をスキップするためのパラメータskip_verifyをサポートしていますが、より高度なTLS構成のためにはOpenDB
メソッドが必要です - これは構成を渡すことを許可します。
認証
OpenDB
を使用している場合、認証情報は通常のオプションを介して渡すことができます。DSNベースの接続の場合、ユーザー名とパスワードは接続文字列にパラメータとして渡すことができ、またはアドレスにエンコードされた認証情報として渡すことができます。
実行
接続が取得された後、ユーザーはExecメソッドを介してsql
文を実行できます。
このメソッドはコンテキストを受け取ることをサポートしていません - デフォルトでは、バックグラウンドコンテキストで実行されます。ユーザーはExecContext
を使用する必要があります - コンテキストの使用を参照してください。
バッチ挿入
バッチセマンティクスは、Being
メソッドを使用してsql.Tx
を作成することによって実現できます。これを使用してINSERT
文でPrepare
メソッドを使用してバッチを取得できます。これにより、行をExec
メソッドを介して追加できるsql.Stmt
が返されます。バッチは、元のsql.Tx
でCommit
が実行されるまでメモリに累積されます。
行のクエリ
単一行のクエリは、QueryRow
メソッドを使用して達成できます。これは*sql.Row
を返し、Scanを呼び出して列をマージするための変数へのポインタを指定できます。QueryRowContext
のバリアントは、バックグラウンド以外のコンテキストを渡すことを可能にします - コンテキストの使用を参照してください。
複数行を反復処理するには、Query
メソッドが必要です。これは、行を反復処理するためにNextを呼び出す*sql.Rows
構造体を返します。QueryContext
に相当するものを使用して、コンテキストを渡すことができます。
非同期挿入
非同期挿入は、ExecContext
メソッドを介して挿入を実行することによって達成できます。これは、以下のように非同期モードを有効にしたコンテキストを渡す必要があります。これにより、クライアントが挿入の完了を待機するか、データが受信され次第応答するかを指定できます。これは、wait_for_async_insertパラメータを効果的に制御します。
列指向挿入
標準インターフェースではサポートされていません。
構造体の使用
標準インターフェースではサポートされていません。
型変換
標準のdatabase/sql
インターフェースは、ClickHouse APIと同じ型をサポートするべきです。主に複雑な型に関しては、いくつかの例外があります。クライアントは、挿入とレスポンスのマージに関してできるだけ柔軟であることを目指しています。詳細は型変換を参照してください。
複雑な型
特に記載がない限り、複雑な型の取り扱いはClickHouse APIと同じであるべきです。違いはdatabase/sql
の内部によるものです。
マップ
ClickHouse APIとは異なり、標準APIではスキャンタイプでマップを強く型指定する必要があります。例えば、ユーザーはMap(String,String)
フィールドに対してmap[string]interface{}
を渡すことができず、代わりにmap[string]string
を使用する必要があります。interface{}
変数は常に互換性があり、より複雑な構造に使用できます。構造体は読み取り時にサポートされていません。
挿入の動作はClickHouse APIと同じです。
圧縮
標準APIは、ネイティブのClickHouse APIと同じ圧縮アルゴリズム(すなわち、lz4
およびzstd
)をサポートします。また、HTTP接続のためにgzip、deflate、br圧縮もサポートされています。これらのいずれかが有効にされると、挿入時とクエリレスポンス時にブロックで圧縮が行われます。他のリクエスト(例:ピングやクエリリクエスト)は圧縮されずに残ります。これは、lz4
およびzstd
オプションと一貫しています。
接続を確立するためにOpenDB
メソッドを使用する場合、Compression構成を渡すことができます。これには、圧縮レベルを指定する機能が含まれています(以下を参照)。DSN経由でsql.Open
を使用する場合、compress
パラメータを利用します。これは、特定の圧縮アルゴリズム(すなわち、gzip
、deflate
、br
、zstd
またはlz4
)またはブールフラグであることができます。true
に設定すると、lz4
が使用されます。デフォルトはnone
(圧縮無効)です。
適用される圧縮レベルは、DSNパラメータcompress_levelまたはCompressionオプションのLevelフィールドによって制御できます。これはデフォルトで0ですが、アルゴリズムに特異です:
gzip
--2
(最良の速度)から9
(最良の圧縮)deflate
--2
(最良の速度)から9
(最良の圧縮)br
-0
(最良の速度)から11
(最良の圧縮)zstd
、lz4
- 無視されます。
パラメータバインディング
標準APIは、ClickHouse APIと同じパラメータバインディング機能をサポートし、Exec
、Query
、QueryRow
メソッド(およびその相当のContextバリアント)にパラメータを渡すことができます。位置指定、名前付き、番号付きのパラメータがサポートされています。
特別なケースに関しては、依然として適用されます。
コンテキストの使用
標準APIは、ClickHouse APIと同様に、コンテキストを介して期限、キャンセルシグナル、その他のリクエストスコープの値を渡す機能をサポートしています。ClickHouse APIとは異なり、これはメソッドのContext
バリアントを使用して達成されます。すなわち、デフォルトでバックグラウンドコンテキストを使用するメソッド(例:Exec
)には、コンテキストを最初のパラメータとして渡すことができるバリアントExecContext
があります。これにより、アプリケーションフローの任意の段階でコンテキストを渡すことができます。たとえば、ユーザーは、ConnContext
を介して接続を確立する際や、QueryRowContext
を介してクエリ行をリクエストする際にコンテキストを渡すことができます。以下に使用可能なすべてのメソッドの例を示します。
期限、キャンセルシグナル、クエリID、クォータキー、接続設定を渡すためにコンテキストを使用する詳細については、ClickHouse APIのコンテキストの使用を参照してください。
セッション
ネイティブ接続は本質的にセッションを持っていますが、HTTP経由の接続では、ユーザーが設定としてコンテキストを渡すためのセッションIDを作成する必要があります。これにより、セッションにバインドされた一時テーブルなどの機能を使用できるようになります。
動的スキャン
ClickHouse API と同様に、カラムタイプ情報が利用可能で、ユーザーは正しい型の変数のランタイムインスタンスを作成し、Scan に渡すことができます。これにより、型が不明なカラムを読み取ることが可能になります。
外部テーブル
外部テーブル は、クライアントが SELECT
クエリを用いて ClickHouse にデータを送信することを可能にします。このデータは一時テーブルに格納され、クエリ自体の評価に使用できます。
クエリを使用して外部データをクライアントに送信するには、ユーザーはコンテキストを介して送信する前に ext.NewTable
を使用して外部テーブルを構築する必要があります。
オープンテレメトリ
ClickHouse は、トレースコンテキスト をネイティブプロトコルの一部として渡すことを許可します。クライアントは clickhouse.withSpan
関数を使用して Span を作成し、これをコンテキストを介して渡すことができます。これは HTTP が輸送手段として使用される場合にはサポートされていません。
パフォーマンステips
- 可能な限り ClickHouse API を活用してください。特にプリミティブ型の場合、これは重大なリフレクションや間接参照を回避します。
- 大規模データセットを読み取る場合は、
BlockBufferSize
を変更することを検討してください。これによりメモリ使用量は増加しますが、行の反復処理中により多くのブロックを並行してデコードできます。デフォルト値の 2 は保守的で、メモリオーバーヘッドを最小化します。より大きな値はメモリ内のブロックを増やします。これは、異なるクエリが異なるブロックサイズを生成できるため、テストが必要です。そのため、これはコンテキストを介してクエリレベルで設定することができます。 - データを挿入する際には、型を明確にしてください。クライアントはUUIDやIPのために文字列の解析を許可するなど柔軟であることを目指していますが、これにはデータ検証が必要で、挿入時にコストがかかります。
- 可能な場合は列指向の挿入を使用してください。これも強く型付けされるべきで、クライアントが値を変換する必要を回避します。
- 最適な挿入パフォーマンスのために ClickHouse の推奨事項に従ってください。