非常に標準的なデータプロセスがあります。 最も生の形式の生データは、単一のリポジトリ(この場合はBigQuery)に定期的にアップロードされます。 一部のソース(自社のプロダクション)からは1時間ごとにデータが送信され、他のソース(通常はサードパーティのソース)からは毎日データが送信されます。
その後、データはさまざまなユーザーによって使用可能な状態に処理されます。 これらは内部ダッシュボードである場合があります。 パートナーへの報告。 生産に入り、製品の動作に影響する結果。 これらの操作は非常に複雑になる可能性があり、複数のデータソースが含まれます。 しかし、ほとんどの場合、SQL + UDFを使用してBigQuery内でこれを処理します。 結果は、同じ場所の別々のテーブルに保存されます。
この処理を整理する明白な方法は、操作のスケジュールを作成することです。 データが毎日午前1時にロードされる場合、処理を01:05に設定します。 このデータソースが各時間の5分目の領域にロードされる場合、各時間の10分に処理を構成します。 5分間のギャップはユーザーにとって重要ではなく、すべてが機能するはずです。
しかし、世界は残酷です! データは必ずしも時間通りに到着するとは限りません。 または、修理されていなければ、まったく来ません。 1時間ごとのダウンロードが11分に完了し、変換が10分に開始された場合は、ダッシュボードにこのデータが表示されるまでさらに1時間お待ちください。 また、操作で複数のソースを使用する場合、状況はさらに楽しくなります。
さらに、ロードされた生データは常に正しいとは限りません(データは通常常に間違っています!)。 定期的に、データをクリーニングまたはリロードする必要があります。 そして、すべてが修復されるように、正しいパラメーターですべての操作を再開する必要があります。
これはもちろん、生データに関する問題であり、それらを解決する必要があります。 しかし、これは完全に打ち負かすことのできない戦争です。 それでも何かが壊れます。 データソースが内部の場合、開発者は追跡の信頼性ではなく、新しいクールな機能で忙しくなります。 これがサードパーティのデータである場合、通常はパイプです。 少なくとも処理が邪魔にならないようにしたいと思います。生データが修復されるとすぐに、すべての顧客がすぐに正しい結果を見ました。
これは本当に大きな問題です。 そして、他にどのように決定するのですか?
解決策1-問題の詳細を削除する
処理が問題を引き起こす場合、それをしないでください! 処理を行ったり、中間結果を保存したりする必要はありません。 ユーザーが結果を必要とするとすぐに、生データからすべてをその場で計算する必要があります。 BigQueryの速度を考えると、これは非常に現実的です。 特に、データを使用して行うのがGROUP BYの日付とカウント(1)であり、過去14日間のデータのみが必要な場合です。
ほとんどの分析は、このようなクエリで特に機能します。 そのため、このソリューションを積極的に使用しています。 ただし、このアプローチは複雑な変換では機能しません。
1つの問題はコードの複雑さです。 すべての操作を1つのSQLクエリに追加すると、読み取られません。 幸いなことに、これはタイプviewのテーブルを通じて達成されます 。 これらはBigQueryの論理テーブルです。データは格納されませんが、SQLクエリからその場で生成されます。 これにより、コードが大幅に簡素化されます。
しかし、別の問題はパフォーマンスです。 ここではすべてが悪いです。 どんなに高速で安価な最新のデータベースであっても。 1年間の履歴データで複雑な変換を実行すると、時間と費用がかかります。 他のオプションはありません。 この問題により、この戦略はかなりの割合の場合に適用できなくなります。
決定番号2-複雑なシステムを構築する
処理制御システムなしで行う方法がない場合は、このシステムをうまく構築する必要があります。 cronスクリプトの実行スケジュールだけでなく、いつどのような変換を開始するかを決定するデータ読み込み監視システム。 おそらく、 pub / subパターンが非常に適しています。
しかし、問題があります。 複雑なシステムの構築が多かれ少なかれ単純な場合、それを維持してバグをキャッチすることは非常に困難です。 コードが多いほど、問題が多くなります。
幸いなことに、3番目の解決策があります。
ソリューション番号3-ラムダアーキテクチャ! ...まあ、ある種の
Lambdaアーキテクチャは、スケジュールされたリアルタイムのデータ処理を活用する有名なデータ処理アプローチです。
*ロシア語に適切に翻訳する方法がわかりませんが、バッチジョブはバッチジョブですか? 誰が知っている、教えて!
通常、これはすべて複数のソリューションを使用して構築されます。 ただし、BigQueryの内部では基本的に同じトリックを使用します。
そして、これがどのように機能するかです:
スケジュールされた処理(バッチレイヤー)。 毎日、現在のデータを変換し、結果をテーブルに保存するSQLクエリを実行します。 すべてのクエリの構造は次のとおりです。
このクエリの結果はtable_staticに保存されます(上書きします)。 はい。BigQueryでは、このクエリで使用されたテーブルにクエリ結果を保存できます。 結果として、すでに計算済みの古いデータを(再集計しないように)取得し、新しいデータと結合します。 X日は、生データに対するすべての可能な調整を考慮するためにデータを再計算するために選択した期間です。 X日間(ソースに対してどれだけの量か)で、すべての調整が既に行われ、破損したものはすべて修復され、データは変更されないと想定されています。
リアルタイムアクセス(速度層+サービス層)。 これらのタスクは両方とも、単一のSQLクエリに結合されます。
はい、これは同じリクエストです! table_liveという名前のビューとして保存し、すべてのユーザー(ダッシュボード、他のクエリなど)がこのビューから結果を描画します。 BigQueryのビューは論理レベル(データではなくクエリのみ)で保存されるため、アクセスされるたびに、直近のX日間を再計算し、元のデータのすべての変更が結果に反映されます。
どちらの場合もリクエストは同じであるため、実際にはコードの重複を避けるため、(バッチレイヤーからの)毎日のリクエストは次のようになります。
SELECT * FROM table_live
(および結果をtable_staticに保存します)
このアプローチには、いくつかの重要な利点があります。
- 各ユーザーは関連する結果を受け取り、生データと集約データの間で再同期はありません(生データを含むすべての妨害がX日間許可されている場合)
- ユーザーはすぐに結果を取得します。 アクセスされるたびに2年間のデータを再集計する人はいません。 BigQueryで過去X日間を再計算するのは許容できるほど高速です。 Xは、パフォーマンスの問題が発生しないように選択されます。 もちろん、日ではなく時間に切り替えることができますが、データを使用してこれを行う必要はありませんでした。
- 日常業務のスケジュールについて考える必要はありません。 これは1日に1回行うだけで済みますが、生データの読み込み時間には依存しません。 また、変換が1日に落ちても、2回起動されても問題はありません。 ユーザーが問題に気付くには、処理がX日間以上「置かれる」必要があります。
- このようなシステムを構築するには、最小限のコード(読み取り-問題)が必要です。 SQLクエリ自体は元のクエリよりも10行長く、BigQuery内にビューとして保存されるようになりました。 さらに、毎日の処理を実行する必要がありますが、これは基本的なタスクです。
- このシステムのコストは、スケジュールの複雑なシステムを作成する場合よりもさらに低くなる可能性があります。 私たちは常にX日を数えているので、もっと高価になるはずです。 しかし、私たちの経験は、その逆が真実であることを示しています。 1時間ごとにデータをアップロードする場合、週末も含めて1時間ごとに再集計する必要があります。 また、調整を反映するためにX日前に再集計する必要があります。 週の合計は24 * 7 = 168回と入力されます。 しかし、実際には、ユーザーはこのダッシュボードを週に3回しか開くことができません。 私たちのアプローチでは、毎日のスケジュールで7回、さらにその場で3回カウントする必要があります。 大幅に少ない。
PS BigQueryで日付で分割されたテーブルを使用する場合(非常に気に入っています)、これに対する解決策があります。 しかし、これは別の投稿のトピックです。 ヒント-これらのテーブルを操作するための関数は、一部のテーブルが単なる表現である場合、誓いません。
PPS BigQueryのビューがキャッシング(通常のクエリでの動作)をサポートしている場合、それは本当にクールです。 これは本質的にそれらをマテリアライズドビューにします。 そして、このアプローチの有効性はさらに高くなります。 同意する場合- ここにアスタリスクを付けると、この機能をより速く実装できます。