次の方法で共有


Azure Data Explorer で重複データを処理する

クラウドにデータを送信するデバイスは、データのローカル キャッシュを維持します。 データのサイズにもよりますが、ローカルのキャッシュにデータが保存される期間は数日、ときには数か月にも及びます。 不具合が発生したデバイスがキャッシュに保存されたデータを再送信し、分析用データベースにデータの重複が発生した場合でも、分析用データベースに問題が起こらないようにする必要があります。 重複は、クエリによって返されるレコードの数に影響を与える可能性があります。 これは、イベントのカウントなど、レコードの正確な数が必要な場合に関連します。 このトピックでは、そのようなシナリオでデータの重複に対応するためのベスト プラクティスの概要を紹介します。

データの重複に関する最善の対応策は、重複の発生を予防することです。 可能であれば、データ パイプラインの早い段階で問題を修正しましょう。そのようにすれば、データ パイプラインでデータが移動することによるコストを節約できるうえに、システムに取り込まれた重複データへの対応にリソースが消費される事態を回避できます。 これに対して、ソース システムを変更できない状況では、このシナリオに対応する方法が多岐にわたります。

データの重複の影響を把握する

重複したデータの割合を確認します。 重複したデータの割合が明らかになったら、問題の範囲とビジネスに対する影響を分析し、適切な対応策を選択します。

重複したデータの割合を特定するためのクエリの例は次のとおりです。

let _sample = 0.01; // 1% sampling
let _data =
DeviceEventsAll
| where EventDateTime between (datetime('10-01-2018 10:00') .. datetime('10-10-2018 10:00'));
let _totalRecords = toscalar(_data | count);
_data
| where rand()<= _sample
| summarize recordsCount=count() by hash(DeviceId) + hash(EventId) + hash(StationId)  // Use all dimensions that make row unique. Combining hashes can be improved
| summarize duplicateRecords=countif(recordsCount  > 1)
| extend duplicate_percentage = (duplicateRecords / _sample) / _totalRecords  

データの重複への対応策

対応策 #1:重複したデータを削除しない

ビジネス上の要件と、データの重複をどの程度まで許容できるかを把握しましょう。 データセットによっては、重複したデータが一定の割合存在していても問題ありません。 データの重複があっても大きな影響がなければ、その存在を無視してもよいのです。 重複したデータを削除しないことのメリットは、取り込みのプロセスやクエリのパフォーマンスに追加のオーバーヘッドが発生しないという点にあります。

対応策 #2:クエリの最中に行の重複を処理する

クエリの最中にフィルター処理を通じてデータ内の行の重複を除去するという方法もあります。 集合関数 arg_max() を使えば、重複したレコードを除去し、タイムスタンプ (またはそれ以外の列) に基づいて最新のレコードを取得できます。 この方法を使用するメリットは、クエリを実行している間に重複を除去できるため、取り込みが早くなることです。 それに加えて、(重複した分も含めた) レコードすべてが監査とトラブルシューティングに利用できます。 arg_max 関数を使用する方法のデメリットとしては、クエリの実行時間が伸びることと、データにクエリを実行するたびに CPU に負荷がかかることが挙げられます。 クエリの対象となるデータの量によっては、この方法だとうまく機能しなかったり、メモリの消費量が多くなったりすることがあります。その場合には、別の方法に切り替える必要があります。

次の例は、一意のレコードを特定する一連の列を対象に、最後に取り込まれたレコードを取得するクエリです。

DeviceEventsAll
| where EventDateTime > ago(90d)
| summarize hint.strategy=shuffle arg_max(EventDateTime, *) by DeviceId, EventId, StationId

このクエリは、テーブルに対して直接実行する代わりに、関数の中に配置することもできます。

.create function DeviceEventsView
{
    DeviceEventsAll
    | where EventDateTime > ago(90d)
    | summarize arg_max(EventDateTime, *) by DeviceId, EventId, StationId
}

対応策 #3:具体化されたビューを使用して重複を除去する

take_any()/arg_min()/arg_max() の集計関数を使用することで、重複除去のために具体化されたビューを使用できます (具体化されたビューの作成コマンドに関する記事の例 #4 を参照)。

Note

具体化されたビューでは、クラスターのリソースを消費するというコストが発生し、それが無視できるほどではない場合があります。 詳細については、具体化されたビューの「パフォーマンスに関する考慮事項」を参照してください。

解決策 #4: 論理的な削除を使用して重複を削除する

論理的な削除では、個々のレコードを削除する機能がサポートされるため、重複を削除するために使用できます。 このオプションは、頻繁に削除しない場合にのみ使用することをお勧めします。すべての受信レコードを常に重複排除する必要がある場合は推奨されません。

データの重複除去のために具体化されたビューと論理的な削除のいずれかを選択する

重複除去のために具体化されたビューを使用するか、論理的な削除を使用するかの選択に役立つ考慮事項がいくつかあります。

  • 管理とオーケストレーション: 具体化されたビューはフル マネージド ソリューションです。 ビューは 1 回定義され、システムは、すべての受信レコードの重複を処理します。 論理的な削除には、オーケストレーションと管理が必要です。 したがって、使用しているユース ケースで具体化されたビューが機能する場合は、常にこのオプションを選択する必要があります。
  • どのような場合にレコードの重複除去を行うか: 論理的な削除では、重複するレコードが最初にテーブルに追加され、その後削除されます。そのため、取り込みプロセスと論理的な削除のプロセスの間で、テーブルに重複が含まれます。 具体化されたビューでは、ビュー内のレコードは、ビューに入る前に重複除去されるため、常に重複除去されます。
  • 頻度: テーブルを常に重複除去する必要がある場合は、具体化されたビューを使用します。 重複の頻度が低く、取り込み中にそれらを特定できると予想される場合、通常、具体化されたビューよりも論理的な削除プロセスのほうがパフォーマンスが優れています。 たとえば、通常、取り込みには重複がないが、重複が含まれていることが判明しているストリームを取り込む場合です。 このシナリオでは、すべてのレコードの重複を絶えず除去しようとする具体化されたビューを定義するよりも、論理的な削除を使用してこれらの重複を処理する方が適切です。

解決策 #5: ingest-by エクステント タグ

'ingest-by:' エクステント タグ は取り込み中の重複を防ぐために使用できます。 これは、各インジェスト バッチに重複がないことが保証され、同じインジェスト バッチが 2 回以上取り込まれた場合にのみ重複が想定される場合に関係します。

まとめ

データの重複に対処する方法には、さまざまなものがあります。 アカウントの価格とパフォーマンスを考慮しつつ、各種の選択肢を慎重に検討し、ビジネスに最も適した方法を判断するようにしてください。