ClickHouse Rustクライアント
ClickHouseに接続するための公式のRustクライアントで、元々はPaul Loydによって開発されました。クライアントのソースコードはGitHubリポジトリで入手可能です。
概要
- 行のエンコード/デコードには
serde
を使用しています。 serde
属性をサポートしています:skip_serializing
、skip_deserializing
、rename
。- HTTPトランスポートでは
RowBinary
フォーマットを使用します。- TCP経由で
Native
に切り替える計画があります。
- TCP経由で
- TLSをサポートしています(
native-tls
およびrustls-tls
機能を通じて)。 - 圧縮と解凍をサポートしています(LZ4)。
- データの選択や挿入、DDLの実行、およびクライアント側のバッチ処理のためのAPIを提供しています。
- ユニットテスト用の便利なモックを提供しています。
インストール
クレートを使用するには、Cargo.toml
に以下を追加してください:
詳細は、crates.ioページもご覧ください。
Cargo機能
lz4
(デフォルトで有効)—Compression::Lz4
およびCompression::Lz4Hc(_)
バリアントを有効にします。有効にされた場合、デフォルトで全てのクエリにCompression::Lz4
が使用されますが、WATCH
を除きます。native-tls
—hyper-tls
を通じてHTTPS
スキーマのURLをサポートし、OpenSSLにリンクします。rustls-tls
—hyper-rustls
を通じてHTTPS
スキーマのURLをサポートし、OpenSSLにリンクしません。inserter
—client.inserter()
を有効にします。test-util
— モックを追加します。詳細はこちらの例をご覧ください。これはdev-dependencies
でのみ使用してください。watch
—client.watch
機能を有効にします。詳細は対応するセクションを参照してください。uuid
— uuidクレートで作業するためにserde::uuid
を追加します。time
— timeクレートで作業するためにserde::time
を追加します。
ClickHouseにHTTPS
URLを介して接続する場合、native-tls
またはrustls-tls
のいずれかの機能を有効にする必要があります。両方が有効にされている場合は、rustls-tls
機能が優先されます。
ClickHouseバージョンの互換性
このクライアントはLTSまたはそれ以降のバージョンのClickHouseと、ClickHouse Cloudに対応しています。
v22.6より古いClickHouseサーバーは、行バイナリを一部の稀なケースで不正確に処理します。 v0.11以上を使用し、wa-37420
機能を有効にすることでこの問題を解決できます。ただし注意:この機能は新しいClickHouseバージョンでは使用しないでください。
例
クライアントのさまざまな使用シナリオをカバーすることを目指しており、例はクライアントリポジトリでご覧いただけます。概要は例のREADMEで入手可能です。
例や以下の文書に不明な点や欠落がある場合は、お問い合わせください。
使用法
ch2rsクレートは、ClickHouseから行タイプを生成するのに役立ちます。
クライアントインスタンスの作成
作成したクライアントを再利用するか、クローンして基盤となるhyper接続プールを再利用してください。
HTTPSまたはClickHouse Cloud接続
HTTPSはrustls-tls
またはnative-tls
のCargo機能のいずれかで動作します。
通常通りにクライアントを作成してください。この例では、環境変数を使用して接続詳細を保存しています:
URLにはプロトコルとポートの両方を含める必要があります。例:https://instance.clickhouse.cloud:8443
。
詳細は次の通りです:
- クライアントリポジトリのClickHouse Cloudの例は、オンプレミスのHTTPS接続にも適用可能です。
行の選択
- プレースホルダー
?fields
はno, name
(Row
のフィールド)に置き換えられます。 - プレースホルダー
?
は以下のbind()
呼び出しの値に置き換えられます。 - 最初の行またはすべての行を取得するために便利な
fetch_one::<Row>()
およびfetch_all::<Row>()
メソッドが使用できます。 - テーブル名をバインドするために
sql::Identifier
を使用できます。
注意:レスポンス全体がストリームされるため、カーソルは行を生成した後でもエラーを返すことがあります。この場合、query(...).with_option("wait_end_of_query", "1")
を試して、サーバー側でのレスポンスバッファリングを有効にしてください。詳細もご覧ください。buffer_size
オプションも便利です。
行を選択する際にwait_end_of_query
を使用する際は注意してください。サーバー側でのメモリ消費が増加し、全体のパフォーマンスが低下する可能性があります。
行の挿入
end()
が呼び出されない場合、INSERT
は中止されます。- 行はストリームとして徐々に送信され、ネットワーク負荷を分散します。
- ClickHouseは、すべての行が同じパーティションに収まる場合にのみバッチを原子的に挿入します。この際、行の数は
max_insert_block_size
よりも少ない必要があります。
非同期挿入(サーバー側バッチ処理)
ClickHouseの非同期挿入を使用して、クライアント側のデータバッチ処理を回避できます。これは、単にinsert
メソッド(またはクライアントインスタンス自体に)にasync_insert
オプションを提供することで行えます。
詳細は次の通りです:
- クライアントリポジトリの非同期挿入の例をご覧ください。
Inserter機能(クライアント側バッチ処理)
inserter
のCargo機能が必要です。
Inserter
は、いずれかのしきい値(max_bytes
、max_rows
、period
)に達した場合、commit()
内でアクティブな挿入を終了します。- アクティブな
INSERT
を終了する間隔は、並行する挿入者による負荷のスパイクを避けるためにwith_period_bias
を使用して調整できます。 Inserter::time_left()
は、現在の期間が終了する時を検出するために使用できます。ストリームがアイテムをまれに発生する場合は、制限を再確認するためにInserter::commit()
を再度呼び出してください。- 時間のしきい値は、quantaクレートを使用して
inserter
を高速化します。test-util
が有効な場合は使用されません(したがって、カスタムテストでtokio::time::advance()
による時間管理が可能です)。 commit()
コール間のすべての行は、同じINSERT
文で挿入されます。
挿入を終了/確定する場合は、フラッシュを忘れないでください:
DDLの実行
単一ノードの展開では、次のようにDDLを実行するだけで十分です。
ただし、負荷分散装置またはClickHouse Cloudを使用したクラスター展開では、wait_end_of_query
オプションを使用して、すべてのレプリカでDDLが適用されるのを待つことをお勧めします。これは次のように行うことができます。
ClickHouse設定
with_option
メソッドを使用して、さまざまなClickHouse設定を適用できます。例として:
query
に加えて、insert
およびinserter
メソッドでも同様に機能します。また、クライアントインスタンス上で同じメソッドを呼び出すことで、すべてのクエリに対してグローバル設定を設定できます。
クエリID
.with_option
を使用することで、クエリをClickHouseのクエリログで識別するためのquery_id
オプションを設定できます。
query
に加えて、insert
およびinserter
メソッドでも同様に機能します。
query_id
を手動で設定する場合は、一意であることを確認してください。UUIDは良い選択です。
詳細は、クライアントリポジトリのquery_id例をご覧ください。
セッションID
query_id
と同様に、session_id
を設定して同一のセッション内でステートメントを実行できます。session_id
は、クライアントレベルでグローバルに設定することも、query
、insert
、またはinserter
呼び出しごとに設定することもできます。
クラスター展開の場合、「スティッキーセッション」がないため、特定のクラスターノードに接続してこの機能を適切に利用する必要があります。たとえば、ラウンドロビン負荷分散装置は、後続のリクエストが同じClickHouseノードで処理されることを保証しません。
詳細は、クライアントリポジトリのsession_id例をご覧ください。
カスタムHTTPヘッダー
プロキシ認証を使用している場合やカスタムヘッダーを渡す必要がある場合は、次のようにできます。
詳細は、クライアントリポジトリのカスタムHTTPヘッダーの例をご覧ください。
カスタムHTTPクライアント
これは、基盤となるHTTP接続プール設定を微調整するのに役立ちます。
この例はレガシーHyper APIに依存しており、将来的に変更される可能性があります。
詳細は、クライアントリポジトリのカスタムHTTPクライアントの例をご覧ください。
データ型
(U)Int(8|16|32|64|128)
は、対応する(u|i)(8|16|32|64|128)
型またはそれを囲む新しい型にマッピングされます。(U)Int256
は直接サポートされていませんが、回避策があります。Float(32|64)
は、対応するf(32|64)
型またはそれを囲む新しい型にマッピングされます。Decimal(32|64|128)
は、対応するi(32|64|128)
型またはそれを囲む新しい型にマッピングされます。符号付き小数点数の実装には、fixnum
を使用するのが便利です。Boolean
は、bool
またはそれを囲む新しい型にマッピングされます。String
は、&str
、&[u8]
、String
、Vec<u8>
、またはSmartString
などの任意の文字列またはバイト型にマッピングされます。新しい型もサポートされています。バイトを格納するためには、serde_bytes
を使用することを検討してください。こちらの方が効率的です。
FixedString(N)
は、バイトの配列としてサポートされています。例:[u8; N]
。
Enum(8|16)
は、serde_repr
を使用してサポートされています。
UUID
は、serde::uuid
を使用してuuid::Uuid
にマッピングされます。uuid
機能が必要です。
IPv6
は、std::net::Ipv6Addr
にマッピングされます。IPv4
は、std::net::Ipv4Addr
を使用して、serde::ipv4
でマッピングされます。
Date
は、u16
またはそれを囲む新しい型にマッピングされ、1970-01-01
以降の日数を表します。また、time::Date
は、serde::time::date
を使用してサポートされており、time
機能が必要です。
Date32
は、i32
またはそれを囲む新しい型にマッピングされ、1970-01-01
以降の日数を表します。また、time::Date
は、serde::time::date32
を使用してサポートされており、time
機能が必要です。
DateTime
は、u32
またはそれを囲む新しい型にマッピングされ、UNIXエポック以降の経過秒数を表します。また、time::OffsetDateTime
は、serde::time::datetime
を使用してサポートされており、time
機能が必要です。
DateTime64(_)
は、i32
またはそれを囲む新しい型にマッピングされ、UNIXエポック以降の経過時間を表します。また、time::OffsetDateTime
は、serde::time::datetime64::*
を使用してサポートされており、time
機能が必要です。
Tuple(A, B, ...)
は、(A, B, ...)
またはそれを囲む新しい型にマッピングされます。Array(_)
は、任意のスライス(例:Vec<_>
、&[_]
)にマッピングされます。新しい型もサポートされています。Map(K, V)
はArray((K, V))
のように振る舞います。LowCardinality(_)
はシームレスにサポートされています。Nullable(_)
は、Option<_>
にマッピングされます。clickhouse::serde::*
ヘルパーには::option
を追加してください。
Nested
は、名前の付け替えを使って複数の配列を提供することでサポートされています。
Geo
型がサポートされています。Point
はタプル(f64, f64)
のように振る舞い、他の型はポイントのスライスです。
Variant
、Dynamic
、(新しい)JSON
データ型はまだサポートされていません。
モッキング
このクレートは、CHサーバーのモックを作成し、DDL、SELECT
、INSERT
、およびWATCH
クエリをテストするためのユーティリティを提供します。この機能は、test-util
機能を使用して有効化できます。これは開発依存性としてのみ使用してください。
例をご覧ください。
トラブルシューティング
CANNOT_READ_ALL_DATA
CANNOT_READ_ALL_DATA
エラーの最も一般的な原因は、アプリケーション側の行定義がClickHouseの定義と一致しないことです。
以下のテーブルを考慮してください:
次に、アプリケーション側でEventLog
が不一致の型で定義されていると、例えば以下のようになります:
データを挿入すると、次のエラーが発生することがあります:
この例では、EventLog
構造体の正しい定義によって解決されます:
既知の制限
Variant
、Dynamic
、(新しい)JSON
データ型はまだサポートされていません。- サーバー側のパラメータバインディングはまだサポートされていません。これに関してはこの問題で進捗を追跡できます。
お問い合わせ
質問や支援が必要な場合は、Community SlackまたはGitHub issuesを通じてお気軽にお問い合わせください。