概要
- 行のエンコード/デコードに
serdeを使用します。 serdeの属性skip_serializing、skip_deserializing、renameをサポートします。- HTTP トランスポートで
RowBinaryフォーマットを使用します。- 将来的には TCP 上の
Nativeへ切り替える予定です。
- 将来的には TCP 上の
- TLS (
native-tlsおよびrustls-tlsfeatures 経由) をサポートします。 - 圧縮および展開 (LZ4) をサポートします。
- データの選択や挿入、DDL の実行、クライアント側でのバッチ処理のための API を提供します。
- 単体テストに便利なモックを提供します。
インストール
Cargo.toml に追加します。
Cargo フィーチャー
lz4(デフォルトで有効) —Compression::Lz4およびCompression::Lz4Hc(_)のバリアントを有効にします。有効な場合、WATCHを除くすべてのクエリで、デフォルトでCompression::Lz4が使用されます。native-tls— OpenSSL にリンクするhyper-tls経由で、HTTPSスキームの URL をサポートします。rustls-tls— OpenSSL にリンクしないhyper-rustls経由で、HTTPSスキームの URL をサポートします。inserter—client.inserter()を有効にします。test-util— モックを追加します。サンプル を参照してください。使用するのはdev-dependenciesのみとしてください。watch—client.watch機能を有効にします。詳細は該当するセクションを参照してください。uuid— uuid クレート と連携するためにserde::uuidを追加します。time— time クレート と連携するためにserde::timeを追加します。
ClickHouse バージョンの互換性
wa-37420 フィーチャーを有効にできます。注: この機能は、より新しい ClickHouse バージョンでは使用しないでください。
例
使い方
ch2rs クレートを使うと、ClickHouse から行型を生成できます。
クライアントインスタンスの作成
HTTPS または ClickHouse Cloud への接続
rustls-tls または native-tls のいずれの Cargo フィーチャーでも利用できます。
次に、通常どおりクライアントを作成します。この例では、接続情報を保存するために環境変数を使用します。
- クライアントリポジトリのClickHouse Cloud を使用した HTTPS の例も参照してください。これはオンプレミスの HTTPS 接続にも適用できるはずです。
行の選択
- プレースホルダー
?fieldsはno, name(Rowのフィールド) に置き換えられます。 - プレースホルダー
?は、後続のbind()呼び出しで指定された値に置き換えられます。 - 先頭の1行またはすべての行を取得するには、便利な
fetch_one::<Row>()メソッドとfetch_all::<Row>()メソッドをそれぞれ使用できます。 sql::Identifierを使ってテーブル名をバインドできます。
query(...).with_option("wait_end_of_query", "1") を試して、サーバー側でレスポンスのバッファリングを有効にしてください。詳細はこちら。buffer_size オプションも役立つ場合があります。
行を挿入する
end()が呼び出されない場合、INSERTは中断されます。- ネットワーク負荷を分散するため、行はストリームとして順次送信されます。
- ClickHouse でバッチの insert がアトミックに行われるのは、すべての行が同じパーティションに収まり、かつその数が
max_insert_block_size未満の場合に限られます。
非同期 INSERT (サーバー側バッチ処理)
insert メソッドに async_insert オプションを指定するだけです (または Client インスタンス自体に指定すれば、すべての insert 呼び出しに適用されます) 。
- クライアントリポジトリの非同期 INSERT の例
Inserter 機能 (クライアント側バッチ処理)
inserter Cargo feature が必要です。
- いずれかのしきい値 (
max_bytes、max_rows、period) に達すると、Inserterはcommit()で進行中の insert を終了します。 - 並列 inserter による負荷スパイクを避けるため、
with_period_biasを使って、進行中のINSERTを終了する間隔に偏りを持たせることができます。 Inserter::time_left()は、現在の period がいつ終了するかを判定するために使用できます。ストリームでアイテムがまれにしか生成されない場合は、制限を確認するためにInserter::commit()を再度呼び出してください。- 時間しきい値は、
inserterを高速化するために quanta クレート を使用して実装されています。test-utilが有効な場合は使用されません (そのため、カスタムテストではtokio::time::advance()で時間を制御できます) 。 commit()呼び出しの間にあるすべての行は、同じINSERTステートメントで挿入されます。
DDLの実行
wait_end_of_query オプションを使って、DDL がすべてのレプリカに適用されるのを待つことを推奨します。これは次のように実行できます。
ClickHouse設定
with_option メソッドを使用すると、さまざまな ClickHouse設定を適用できます。例:
queryに加え、insertメソッドおよびinserterメソッドでも同様に機能します。さらに、すべてのクエリに共通の設定を行うために、同じメソッドをClientインスタンスに対して呼び出すこともできます。
クエリ ID
.with_option を使うと、query_id オプションを設定して、ClickHouse のクエリログでクエリを識別できます。
query に加え、insert および inserter メソッドでも同様に使用できます。
query_id を手動で設定する場合は、一意になるようにしてください。そのためには UUID が適しています。セッションID
query_id と同様に、session_id を設定すると、同じセッションでステートメントを実行できます。session_id は、クライアントレベルでグローバルに設定することも、query、insert、または inserter の呼び出しごとに設定することもできます。
クラスター化されたデプロイメントでは、“スティッキーセッション” がないため、このフィーチャーを適切に利用するには、特定のクラスター ノード に接続する必要があります。たとえば、ラウンドロビン方式のロードバランサーでは、後続のリクエストが同じ ClickHouse ノードで処理されるとは限りません。
カスタムHTTPヘッダー
カスタムHTTPクライアント
データ型
次の追加例も参照してください。
(U)Int(8|16|32|64|128)は、対応する(u|i)(8|16|32|64|128)型、またはそれらをラップした newtype と相互変換できます。(U)Int256は直接サポートされていませんが、回避策があります。Float(32|64)は、対応するf(32|64)、またはそれらをラップした newtype と相互変換できます。Decimal(32|64|128)は、対応するi(32|64|128)、またはそれらをラップした newtype と相互変換できます。符号付き固定小数点数には、fixnumなどの実装を使うと便利です。Booleanはbool、またはそれをラップした newtype と相互変換できます。Stringは、任意の文字列型またはバイト列型と相互変換できます。たとえば&str、&[u8]、String、Vec<u8>、SmartStringです。newtype もサポートされています。バイト列を保存する場合は、より効率的なserde_bytesの使用を検討してください。
FixedString(N)は、たとえば[u8; N]のようなバイトの配列としてサポートされています。
Enum(8|16)はserde_reprを使ってサポートされています。
UUIDはserde::uuidを使用することでuuid::Uuidと相互変換できます。uuidフィーチャーが必要です。
IPv6はstd::net::Ipv6Addrとの間で相互に変換されます。IPv4はserde::ipv4を使用することで、std::net::Ipv4Addrとの間で相互に変換されます。
Dateはu16またはそれをラップした newtype と相互変換でき、1970-01-01からの経過日数を表します。また、time::Dateもserde::time::dateを使用することでサポートされますが、これにはtime機能が必要です。
Date32はi32またはそれをラップした newtype と相互変換でき、1970-01-01からの経過日数を表します。また、time::Dateもserde::time::date32を使用することでサポートされますが、これにはtimeフィーチャー が必要です。
DateTimeはu32、またはそれをラップした newtype と相互に対応し、UNIX epoch からの経過秒数を表します。また、time::OffsetDateTimeもserde::time::datetimeを使うことでサポートされますが、その場合はtimeフィーチャー が必要です。
DateTime64(_)はi32またはそれをラップした newtype と相互変換でき、UNIX epoch からの経過時間を表します。また、time::OffsetDateTimeもserde::time::datetime64::*を使うことでサポートされますが、その場合はtimeフィーチャー が必要です。
Tuple(A, B, ...)は(A, B, ...)またはそれをラップした newtype と相互に対応します。Array(_)は任意のスライス (例:Vec<_>,&[_]) と相互に対応します。独自型もサポートされます。Map(K, V)はArray((K, V))と同様に振る舞います。LowCardinality(_)は透過的にサポートされます。Nullable(_)はOption<_>と相互に対応します。clickhouse::serde::*ヘルパーを使う場合は::optionを追加してください。
- 複数の配列をリネームして指定することで、
Nestedをサポートできます。
Geo型がサポートされています。Pointは(f64, f64)のタプルとして扱われ、その他の型はいずれもポイントのスライスです。
Variant、Dynamic、(新しい)JSONデータ型はまだサポートされていません。
モック
SELECT、INSERT、WATCH クエリをテストするためのユーティリティを提供します。この機能は test-util フィーチャー を有効にすると利用できます。必ず 開発用依存関係としてのみ使用してください。
Exampleを参照してください。
トラブルシューティング
CANNOT_READ_ALL_DATA
CANNOT_READ_ALL_DATA エラーの最も一般的な原因は、アプリケーション側の行定義が ClickHouse 側の行定義と一致していないことです。
次のテーブルを考えてみましょう。
EventLog が異なる型で定義されている場合:
EventLog 構造体を正しく定義することで修正できます。
既知の制限事項
Variant、Dynamic、 (新しい)JSONデータ型は、まだサポートされていません。- サーバー側のパラメータバインディングは、まだサポートされていません。進捗状況については、this issue を参照してください。