13 KiB
title | description | keywords | |||
---|---|---|---|---|---|
データの挿入 | ClickHouseへのデータの挿入方法 |
|
基本的な例
ClickHouseでおなじみの INSERT INTO TABLE
コマンドを使用できます:
INSERT INTO helloworld.my_first_table (user_id, message, timestamp, metric) VALUES
(101, 'Hello, ClickHouse!', now(), -1.0 ),
(102, 'Insert a lot of rows per batch', yesterday(), 1.41421 ),
(102, 'Sort your data based on your commonly-used queries', today(), 2.718 ),
(101, 'Granules are the smallest chunks of data read', now() + 5, 3.14159 )
動作を確認してみましょう。挿入された4行のデータが表示されるはずです:
SELECT * FROM helloworld.my_first_table
ClickHouseへの挿入とOLTPデータベースとの比較
OLAPデータベースとして、ClickHouseは高性能とスケーラビリティに最適化されており、毎秒何百万行もの挿入を可能にします。これは、高度に並列化されたアーキテクチャ、列指向による高圧縮を組み合わせることで実現されますが、一貫性には妥協があります。具体的には、ClickHouseは追記専用操作に最適化されており、最終的な整合性の保証のみを提供します。
これに対し、PostgresのようなOLTPデータベースは、トランザクション挿入に最適化され、完全なACID準拠を持ち、強い一貫性と信頼性の保証を提供します。PostgreSQLはMVCC(Multi-Version Concurrency Control)を使用して同時トランザクションを処理し、複数のデータバージョンを維持します。これらのトランザクションは、時間内に少数の行になる可能性があり、挿入パフォーマンスを制限する信頼性保証によるオーバーヘッドが発生します。
ClickHouseへの高い挿入パフォーマンスを達成するために、強い一貫性の保証を得る場合、以下に説明するシンプルなルールに従う必要があります。これにより、ClickHouseを初めて使用するユーザーがOLTP挿入戦略を再現する際に一般的に遭遇する問題を回避できます。
挿入時のベストプラクティス
-
大きなバッチサイズ - デフォルトでは、ClickHouseに送信される各挿入は、挿入からのデータと共に保存する必要のある他のメタデータを含むストレージのパートを即座に作成するため、より多くのデータを含む小さな数の挿入を送信することは、より少ないデータを含む多量の挿入を送信することに比べて必要な書き込みの数を減らします。基本的には、1,000行以上、理想的には10,000〜100,000行のかなり大きなバッチでデータを挿入することをお勧めします。詳細はこちら。大きなバッチが不可能な場合は、以下で説明する非同期挿入を使用してください。
-
再試行のための一貫したバッチを確保して冪等性を担保する再試行 - デフォルトでは、ClickHouseへの挿入は同期的であり、同一の場合のみ冪等性があります。MergeTreeエンジンファミリーのテーブルの場合、ClickHouseはデフォルトで自動的に挿入時に重複を除去します。例えば以下のようなケースにおいても挿入は許容されます:
- データを受信したノードに問題がある場合、挿入クエリはタイムアウト(またはより具体的なエラー)し、確認応答が得られません。
- データがノードによって書き込まれたが、ネットワークの中断により、クエリの送信者に確認応答を返すことができない場合、送信者はタイムアウトまたはネットワークエラーを受け取ります。
クライアントの観点からは、(i) と (ii) を区別するのは難しい場合があります。しかし、どちらの場合でも、確認のない挿入は直ちに再試行できます。再試行された挿入クエリが同じ順序で同じデータを含む限り、ClickHouseは(確認されていない)元の挿入が成功した場合、再試行された挿入を自動的に無視します。
-
MergeTreeテーブルまたは分散テーブルへの挿入 - データがシャードされている場合、リクエストを一連のノードに分散させてMergeTree(またはReplicatedテーブル)に直接挿入し、
internal_replication=true
を使用することを推奨します。これにより、ClickHouseはデータを任意のレプリカシャードにレプリケートし、データが最終的に整合性を持つようにします。このクライアントサイドの負荷分散が不便な場合、ユーザーは分散テーブルを介して挿入できます。これにより、ノード間で書き込みが分散されます(やはり、internal_replication=true
を設定します)。このアプローチは、ノードに分散テーブルがある場合、データをローカルで書き込んでからシャードに送信するため、やや性能が劣ります。 -
小さなバッチの非同期挿入を使用する - クライアントサイドのバッチ処理が現実的でないシナリオ、例えば数百または数千の単機能エージェントがログ、メトリクス、トレースなどを送信する観測ユースケースでは、問題や異常を迅速に検出するためにリアルタイムのデータ転送が重要な場合があります。さらに、観測システムのイベントスパイクにより、観測データをクライアントサイドでバッファリングしようとするときに大規模なメモリスパイクや関連する問題が発生するリスクがあります。大きなバッチを挿入できない場合、ユーザーはClickHouseに非同期挿入を使用してバッチ処理を委任できます。非同期挿入では、データはまずバッファに挿入され、その後データベースストレージに書き込まれるか、非同期で書き込まれます。
<img src={require('./images/postgres-inserts.png').default}
class="image" alt="NEEDS ALT" style={{width: '600px'}} />
非同期挿入が有効化されているとき、ClickHouseが (1) 挿入クエリを受け取ると、クエリのデータは (2) まずメモリ内バッファに直ちに書き込まれます。 (1) に非同期で、 (3) 次のバッファフラッシュが行われたときのみ、バッファのデータはソートされてデータベースストレージの一部として書き込まれます。注意点として、バッファがデータベースストレージにフラッシュされる前は、クエリでデータを検索することはできません。バッファフラッシュは設定可能です。
バッファがフラッシュされる前に、同じまたは他のクライアントからの他の非同期挿入クエリのデータがバッファに収集される可能性があります。バッファフラッシュから作成されたパートには、複数の非同期挿入クエリからのデータが含まれる可能性があります。通常、これらのメカニズムはクライアントサイドからサーバーサイド(ClickHouseインスタンス)へのデータバッチシフトとなります。
-
公式クライアントを使用する - ClickHouseは最も人気のあるプログラミング言語でのクライアントを持っています。これらは、挿入が正しく実行されることを保証するように最適化されており、直接またはクエリ、ユーザー、接続レベル設定での有効化により非同期挿入をネイティブにサポートします(例: Goクライアント)。
-
ネイティブフォーマットの推奨 - ClickHouseは挿入(およびクエリ)時に多くの入力フォーマットをサポートしています。これはOLTPデータベースとの大きな違いであり、テーブル関数と連携した外部ソースからのデータ読み込みがより簡単になり、ディスク上のファイルからのデータロードの能力も含まれています。これらのフォーマットはアドホックなデータロードとデータエンジニアリング作業に理想的です。最適な挿入パフォーマンスを達成したいアプリケーションの場合、ユーザーはネイティブフォーマットで挿入するべきです。これはほとんどのクライアント(GoとPython)でサポートされており、サーバーが最小限の作業を必要とするため、最適な選択です。このフォーマットはすでに列指向なので、列指向データをクライアントが生成する必要はなく、インサートをスケールさせる取り組みにおいて考慮されるべきです。代替として、ユーザーはRowBinaryフォーマット(Javaクライアントで使用)の利用を検討できます。ネイティブフォーマットに比べて、書くのが通常より容易な行フォーマットです。JSONのような他の行フォーマットに比べて、圧縮、ネットワークオーバーヘッド、サーバーでの処理においてより効率的です。低い書き込みスループットのユーザーで迅速に統合したい場合は、JSONEachRowフォーマットを利用することもできます。このフォーマットには、ClickHouse内での解析にCPUオーバーヘッドがかかることをユーザーは認識しておく必要があります。
-
HTTPまたはネイティブプロトコル - 多くの伝統的なデータベースとは異なり、ClickHouseはHTTPインターフェースをサポートしています。ユーザーはこれを使用して、上記のフォーマットのいずれかでデータを挿入およびクエリできます。これは、トラフィックをロードバランサで簡単に切り替えることができるため、ClickHouseのネイティブプロトコルよりも好まれることがあります。ネイティブプロトコルでの挿入パフォーマンスには若干の違いが予想され、多少のオーバーヘッドが軽減されます。既存のクライアントはこれらのプロトコルのいずれか(または両方、例: Goクライアント)を使用します。ネイティブプロトコルはクエリの進行を簡単に追跡することを可能にします。
大量データのロード
Postgresから大量データをロードするためにユーザーは以下を使用できます:
PeerDB by ClickHouse
を使用する。これはPostgreSQLデータベースのレプリケーションを自社ホスト型ClickHouseおよびClickHouse Cloudに対して実行するために特別に設計されたETLツールです。開始するにはPeerDB Cloudでアカウントを作成し、セットアップ手順についてはドキュメントを参照してください。- 過去の例で示したように、データを直接読み取るPostgresテーブル関数を使用する。通常は既知のウォーターマーク、例: タイムスタンプに基づくバッチレプリケーションに適しているか、ワンオフ移行の場合です。このアプローチは数千万行にスケールできます。より大きなデータセットを移行したいユーザーは、データのチャンクを扱う複数のリクエストを検討すべきです。各チャンクにはそのパーティションが最終テーブルに移動する前にステージングテーブルを使用できます。失敗したリクエストを再試行することが可能になります。この大量ロード戦略の詳細については、こちらを参照してください。
- データをCSVフォーマットでPostgresからエクスポートできます。その後、ローカルファイルまたはオブジェクトストレージを介してテーブル関数を使用してClickHouseに挿入することができます。
:::note 大量データセットの挿入に関するお手伝いが必要ですか? 大きなデータセットの挿入時に助けが必要な場合や、ClickHouse Cloudにデータをインポートする際にエラーが発生した場合は、support@clickhouse.com までご連絡ください。サポートいたします。 :::