ストリーム処理において、ジョインはデータストリームをリッチ化するための基本的な操作です。しかし、ジョインは「高結合増幅(high join amplification)」と呼ばれる重大な性能問題を引き起こす可能性があります。この記事では、この問題とストリーミングパイプラインへの影響を解説し、さらに RisingWave が導入した新機能 非整列ジョイン(unaligned joins) による解決策を紹介します。
高結合増幅とバックプレッシャーを理解する
高結合増幅は、ジョイン操作において単一の入力レコードが他のストリームまたはテーブル内の多数のレコードと一致し、その結果、大量の出力レコードが生成されるときに発生します。
典型的な例として、ユーザのクリックストリームをユーザプロフィール情報でリッチ化するストリーム同士のジョインを考えてみましょう。
CREATE MATERIALIZED VIEW enriched_clicks AS
SELECT
c.click_id,
c.item_id,
u.user_name
FROM
clicks AS c
JOIN
users AS u ON c.user_id = u.user_id;
もし特定のユーザが非常にアクティブ(例:ボットやヘビーユーザ)である場合、users
ストリーム内のそのユーザプロフィールの単一更新が、clicks
ストリーム内の数千件の既存レコードと一致する可能性があります。これにより、ジョイン演算子から膨大な出力データが一気に生成されます。
この突発的なデータ急増は、後続の演算子(例:集計やシンク)を圧倒し、バックプレッシャーを引き起こします。バックプレッシャーとは、処理が遅い下流演算子が上流演算子に対して出力速度を落とすようシグナルを送る仕組みです。この減速はパイプライン全体に伝播します。
RisingWave のようにチェックポイントバリアを利用してデータの一貫性を保証するフォールトトレラントなストリーム処理システムでは、バックプレッシャーは重大な副作用をもたらします。チェックポイントを完了するには、すべての演算子がバリアを処理する必要があります。バックプレッシャーで停止した遅い演算子はバリアを遅延させ、バリアレイテンシを高めます。これにより、システム全体の処理速度やリカバリ能力が低下します。
非整列ジョインの導入
高結合増幅ジョインによるバックプレッシャーを解決するために、RisingWave は「非整列ジョイン」機能を導入しました。この機能は、問題のあるジョイン演算子をその下流演算子から分離し、性能問題がパイプライン全体に波及するのを防ぎます。
この機能は以下のコマンドでセッションごとに有効化できます:
SET streaming_enable_unaligned_join = true;
有効化すると、RisingWave はジョイン演算子の後に中間バッファを自動的に挿入します。ジョイン演算子は出力をこのバッファに書き込みます。これにより、チェックポイントバリアはバッファ内のデータを待たずに次の演算子へ即座に通過でき、遅い下流演算子が増幅された出力を消費するのを待つ必要がなくなります。
この仕組みによって、高結合増幅ジョインは他のデータフローから効果的に切り離されます。下流演算子がバッファ内の大量データを処理するのに時間がかかっても、チェックポイントバリアはシステム全体を妨げることなく流れ続けます。これによりバリアレイテンシを低く保ち、パイプライン全体の安定性が維持されます。
性能に関する考慮点
非整列ジョインの使用にはトレードオフがあります。具体的には、そのクエリ部分を通過するデータのエンドツーエンドレイテンシがわずかに増加します。これは、中間バッファへの書き込みおよび読み出しのオーバーヘッドによるものです。
しかし、この局所的なレイテンシ増加は、バックプレッシャーによってパイプライン全体が遅延するよりもはるかに望ましいものです。これは問題を局所的に封じ込めるための的確な解決策です。非整列ジョインはバリアレイテンシを解消しますが、バッファ内での潜在的なデータ遅延については引き続き監視し、高負荷データ量を処理するためにクラスターをスケールさせる必要がある場合があります。
例
前述の EC サイトの例にこの機能を適用するには、マテリアライズドビューを作成する前に非整列ジョインを有効にするだけです。
-- 現在のセッションで機能を有効化
SET streaming_enable_unaligned_join = true;
-- ジョインがバックプレッシャーを引き起こす場合、自動的にバッファリングされる
CREATE MATERIALIZED VIEW enriched_clicks AS
SELECT c.click_id, c.item_id, u.user_name
FROM clicks AS c
JOIN users AS u ON c.user_id = u.user_id;
この設定により、RisingWave はジョインの出力をバッファリングし、高結合増幅によって下流演算子が停止するのを防ぎ、チェックポイントが迅速に完了するよう保証します。
まとめ
高結合増幅はストリーム処理パイプラインの性能と安定性を低下させる一般的なバックプレッシャー要因です。RisingWave の非整列ジョイン機能は、問題のあるジョインを分離することで、他のデータフローを応答性の高い状態に保つ直接的かつ効果的な解決策を提供します。
- この機能の詳細については、高結合増幅ジョインの分離 を参照してください。
- 今すぐ RisingWave を試す: RisingWave のオープンソース版をダウンロード し、自分のインフラにデプロイしましょう。
RisingWave は、リアルタイムイベントデータを最もシンプルに、最もコスト効率高く処理、分析、管理できるように設計された、ストリーム処理および管理のためのオープンソースプラットフォームです。PostgreSQL互換の SQLインターフェイス と DataFrameスタイルの Pythonインターフェイス の両方を備え、Apache Iceberg™ のオープンテーブルフォーマットを組み込みでサポートしています。
RisingWave は秒間数百万イベントを取り込み、ライブストリームと履歴データを継続的に結合・分析し、低レイテンシでのアドホッククエリ処理、さらに最新かつ一貫性のある結果を Apache Iceberg™ や他の下流システムへ永続化できます。