ClickHouse Rust Client
ClickHouseへの接続のための公式Rustクライアントで、元々はPaul Loydによって開発されました。クライアントのソースコードはGitHubリポジトリにあります。
概要
- 行のエンコーディング/デコーディングに
serde
を使用。 serde
属性をサポート:skip_serializing
、skip_deserializing
、rename
。RowBinary
形式をHTTPトランスポート上で使用。- TCP経由で
Native
に切り替える計画があります。
- TCP経由で
- TLS(
native-tls
およびrustls-tls
機能を通じて)をサポート。 - 圧縮および解凍(LZ4)をサポート。
- データの選択または挿入、DDLの実行、およびクライアントサイドのバッチ処理用のAPIを提供。
- ユニットテスト用の便利なモックを提供。
インストール
クレートを使用するには、Cargo.toml
に以下を追加します。
他の情報: crates.ioページ。
Cargo機能
lz4
(デフォルトで有効) —Compression::Lz4
とCompression::Lz4Hc(_)
バリアントを有効にします。これが有効な場合、WATCH
を除くすべてのクエリに対してデフォルトでCompression::Lz4
が使用されます。native-tls
— OpenSSLにリンクして、HTTPS
スキーマのURLをサポートします。rustls-tls
— OpenSSLにリンクせず、hyper-rustls
を介してHTTPS
スキーマのURLをサポートします。inserter
—client.inserter()
を有効にします。test-util
— モックを追加します。例を参照。開発依存関係でのみ使用してください。watch
—client.watch
機能を有効にします。詳細は該当するセクションを参照してください。uuid
— uuidクレートと連携するためにserde::uuid
を追加します。time
— timeクレートと連携するためにserde::time
を追加します。
HTTPS
URL経由でClickHouseに接続する際は、native-tls
またはrustls-tls
機能のいずれかを有効にする必要があります。
両方が有効な場合は、rustls-tls
機能が優先されます。
ClickHouseバージョンの互換性
このクライアントは、LTSまたはそれ以降のClickHouseバージョン、ならびにClickHouse Cloudに対応しています。
ClickHouseサーバーがv22.6未満の場合、RowBinaryを奇妙に処理します。この問題を解決するには、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例。これはオンプレミスの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
メソッド(または、Client
インスタンス自体)にasync_insert
オプションを提供することで行えます。
他に:
- 非同期挿入の例をクライアントリポジトリで確認してください。
Inserter機能(クライアントサイドバッチ処理)
inserter
Cargo機能が必要です。
Inserter
は、任意の閾値(max_bytes
、max_rows
、period
)に達した場合にcommit()
でアクティブな挿入を終了します。- アクティブな
INSERT
を終了させる間隔は、with_period_bias
を使用してバイアスをかけることができ、並列挿入による負荷のスパイクを回避します。 Inserter::time_left()
を使用して、現在の期間が終了するタイミングを検出できます。アイテムが稀にしか発生しない場合は、Inserter::commit()
を再度呼び出して制限を確認します。- 時間閾値は、
inserter
を高速化するためにquantaクレートを使用して実装されます。test-util
が有効な場合は使用されません(したがって、カスタムテストではtokio::time::advance()
で時間を管理できます)。 commit()
呼び出しの間のすべての行は、同じINSERT
ステートメントで挿入されます。
挿入を終了/最終化したい場合は、フラッシュを忘れないでください:
DDLの実行
単一ノードのデプロイメントでは、次のようにしてDDLを実行するだけで済みます:
しかし、ロードバランサーまたはClickHouse Cloudでのクラスターデプロイメントでは、すべてのレプリカにDDLが適用されるのを待つことをお勧めします。これにはwait_end_of_query
オプションを使用します。次のように行うことができます:
ClickHouse設定
with_option
メソッドを使用して、さまざまなClickHouse設定を適用できます。例えば:
query
に加え、insert
およびinserter
メソッドでも同様に機能します。さらに、同じメソッドをClient
インスタンスで呼び出して、すべてのクエリに対するグローバル設定を設定できます。
クエリID
.with_option
を使用して、ClickHouseのクエリログでクエリを識別するためにquery_id
オプションを設定できます。
query
に加え、insert
およびinserter
メソッドでも同様に機能します。
query_id
を手動で設定する場合は、それがユニークであることを確認してください。UUIDが良い選択です。
他にも:query_idの例をクライアントリポジトリで確認してください。
セッションID
query_id
と同様に、同じセッション内でステートメントを実行するためにsession_id
を設定できます。session_id
は、クライアントレベルでグローバルに設定するか、query
、insert
、またはinserter
呼び出しごとに設定することができます。
クラスターデプロイメントでは、"sticky sessions"がないため、この機能を適切に利用するには、_特定のクラスターノード_に接続する必要があります。例えば、ラウンドロビンロードバランサーは、次のリクエストが同じ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
は、uuid::Uuid
にマッピングされ、serde::uuid
を使用します。uuid
機能が必要です。
IPv6
は、std::net::Ipv6Addr
にマッピングされます。IPv4
は、std::net::Ipv4Addr
にマッピングされ、serde::ipv4
を使用します。
Date
は、u16
またはそれに基づく新しい型にマッピングされ、1970-01-01
以来の経過日数を表します。また、serde::time::date
を使用して、time::Date
もサポートされています。これにはtime
機能が必要です。
Date32
は、i32
またはそれに基づく新しい型にマッピングされ、1970-01-01
以来の経過日数を表します。また、serde::time::date32
を使用して、time::Date
もサポートされています。これにはtime
機能が必要です。
DateTime
は、u32
またはそれに基づく新しい型にマッピングされ、UNIXエポックからの経過秒数を表します。また、serde::time::datetime
を使用して、time::OffsetDateTime
もサポートされています。これにはtime
機能が必要です。
DateTime64(_)
は、i32
またはそれに基づく新しい型にマッピングされ、UNIXエポックからの経過時間を表します。また、serde::time::datetime64::*
を使用して、time::OffsetDateTime
もサポートされています。これには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
データ型はまだサポートされていません。- サーバーサイドのパラメータバインディングはまだサポートされていません。詳細はthis issueを参照してください。
お問い合わせ
質問や支援が必要な場合は、コミュニティSlackまたはGitHubのIssuesを通じて気軽にご連絡ください。