クエリの制限

Kusto は、大規模なデータセットをホストし、関連するすべてのデータをメモリ内に保持することでクエリを満たそうとするアドホック クエリ エンジンです。 クエリによってサービス リソースが際限なく独占されるという固有のリスクがあります。 Kusto には、既定のクエリ制限という形でいくつかの組み込みの保護が用意されています。 これらの制限を削除することを検討している場合は、まず、その結果として実際に何かメリットがあるかどうかを判断してください。

要求の同時実行に対する制限

要求の同時実行は、クラスターによって、同時に実行される複数の要求に対して課される制限です。

  • この制限の既定値は、クラスターが実行されている SKU によって変わり、Cores-Per-Node x 10 として計算されます。
    • たとえば、各マシンに 16 個の仮想コアがある D14v2 SKU に設定されているクラスターの場合、既定の制限は です 16 cores x10 = 160
  • default ワークロード グループの要求レート制限ポリシーを構成すると、既定値を変更できます。
    • クラスター上で同時に実行できる要求の実際の数は、さまざまな要因によって変わります。 最も重要な要因は、クラスター SKU、クラスターの使用可能なリソース、使用パターンです。 ポリシーは、運用環境に似た使用パターンで実行される負荷テストに基づいて構成できます。

詳細については、「Azure Data Explorer を使用した高いコンカレンシーの最適化」を参照してください。

結果セット サイズに対する制限 (結果の切り捨て)

結果の切り捨ては、クエリによって返される結果セットに既定で設定される制限です。 Kusto では、クライアントに返されるレコード数が 500,000 に制限され、そのレコードの全体的なデータ サイズは 64 MB に制限されています。 これらの制限を超えた場合、クエリは "部分的なクエリ エラー" で失敗します。 全体のデータ サイズを超えると、次のメッセージの例外が生成されます。

The Kusto DataEngine has failed to execute a query: 'Query result set has exceeded the internal data size limit 67108864 (E_QUERY_RESULT_SET_TOO_LARGE).'

レコード数を超えると、次のような例外が発生して失敗します。

The Kusto DataEngine has failed to execute a query: 'Query result set has exceeded the internal record count limit 500000 (E_QUERY_RESULT_SET_TOO_LARGE).'

このエラーを処理するには、いくつかの方法があります。

  • 必要なデータのみを返すようにクエリを変更することで、結果セットのサイズを小さくします。 この戦略は、最初に失敗したクエリが "広範" である場合に役立ちます。 たとえば、不要なデータ列がクエリに反映されていない場合です。
  • 集計など、クエリ後の処理をクエリ自体に移動することで、結果セットのサイズを小さくします。 この戦略は、クエリの出力が別の処理システムに送られ、そこで他の集計が行われるシナリオで役立ちます。
  • サービスから大量のデータ セットをエクスポートする場合は、クエリからデータのエクスポートの使用に切り替えます。
  • 次に示す set ステートメントまたはクライアント要求プロパティのフラグを使用して、このクエリ制限を抑制するようにサービスに指示します。

クエリによって生成される結果セットのサイズを小さくするには、次のような方法があります。

  • summarize 演算子グループを使用して、クエリ出力内の類似レコードを集計します。 take_any 集計関数を使用して、いくつかの列をサンプリングすることもできます。
  • take 演算子を使用してクエリ出力をサンプリングします。
  • substring 関数を使用して、幅の広いフリーテキスト列をトリミングします。
  • project 演算子を使用して、結果セットから不要な列を削除します。

notruncation 要求オプションを使用して、結果の切り捨てを無効にすることができます。 ただし、何らかの形式の制限を設定しておくことをお勧めします。

例:

set notruncation;
MyTable | take 1000000

truncationmaxsize (バイト単位の最大データ サイズ、既定値は 64 MB) と truncationmaxrecords (最大レコード数、既定値は 500,000) の値を設定することで、結果の切り捨てをより細かく制御することもできます。 たとえば、次のクエリでは、1,105 件のレコードまたは 1 MB のいずれかを超えたときに結果の切り捨てが発生するように設定されます。

set truncationmaxsize=1048576;
set truncationmaxrecords=1105;
MyTable | where User=="UserId1"

結果の切り捨て制限を削除することは、大量のデータが Kusto から移動されることを意味します。

結果の切り捨て制限を削除できるのは、.export コマンドを使用してエクスポートする目的がある場合、または後で集計する場合です。 後で集計する場合は、Kusto を使用して集計することを検討してください。

Kusto には、呼び出し元にストリーミングすることで、"非常に大規模な" 結果を処理できるようにするクライアント ライブラリが多数用意されています。 このようなライブラリのいずれかを使用して、ストリーミング モードに構成します。 たとえば、.NET Framework クライアント (Microsoft.Azure.Kusto.Data) を使用して、接続文字列のストリーミング プロパティを true に設定するか、ExecuteQueryV2Async() の呼び出しを使用して常に結果をストリーミングするようにします。 ExecuteQueryV2Async() の使用方法の例については、HelloKustoV2 アプリケーションを参照してください。

また、C# ストリーミング インジェストのサンプル アプリケーションに関する記事も役に立つ場合があります。

結果の切り捨ては、クライアントに返される結果のストリームだけでなく、既定で適用されます。 また、既定で、あるクラスターから別のクラスターにクロスクラスター クエリで発行されるサブクエリにも適用され、同様の効果があります。

複数の結果の切り捨てプロパティの設定

set ステートメントを使用する場合、またはクライアント要求のプロパティでフラグを指定する場合は、次のことが適用されます。

  • notruncation が設定されて、truncationmaxsizetruncationmaxrecordsquery_take_max_records のいずれかも設定されている場合、notruncation は無視されます。
  • truncationmaxsizetruncationmaxrecords または query_take_max_records が複数回設定されている場合は、各プロパティの "小さい" 方の値が適用されます。

クエリ演算子によって消費されるメモリの制限 (E_RUNAWAY_QUERY)

Kusto では、各クエリ演算子が "暴走" クエリから保護するために使用できるメモリを制限します。 この制限は、メモリ内の重要なデータを保持することによって動作する、 や summarizeなどのjoin一部のクエリ演算子によって達成される可能性があります。 既定では、制限は 5 GB (クラスター ノードあたり) であり、要求オプション maxmemoryconsumptionperiteratorを設定することで増やすことができます。

set maxmemoryconsumptionperiterator=68719476736;
MyTable | summarize count() by Use

この制限に達すると、テキスト E_RUNAWAY_QUERYを含むメッセージを含む部分的なクエリ エラーが生成されます。

The ClusterBy operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete E_RUNAWAY_QUERY.

The DemultiplexedResultSetCache operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The ExecuteAndCache operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The HashJoin operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The Sort operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The Summarize operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The TopNestedAggregator operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The TopNested operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

maxmemoryconsumptionperiterator が複数回設定されている場合 (たとえばクライアント要求のプロパティと set ステートメントの両方を使用)、低い方の値が適用されます。

部分的なクエリエラーを E_RUNAWAY_QUERY 引き起こす可能性のある追加の制限は、1 つの演算子によって保持される文字列の最大累積サイズに対する制限です。 この制限は、上記の要求オプションではオーバーライドできません。

Runaway query (E_RUNAWAY_QUERY). Aggregation over string column exceeded the memory budget of 8GB during evaluation.

この制限を超えると、関連するクエリ演算子は、summarizeまたは make-seriesである可能性がjoin高くなります。 制限を回避するには、 シャッフル クエリ戦略を使用するようにクエリを変更する必要があります。 (これは、クエリのパフォーマンスを向上させる可能性もあります)。

のすべての場合において、追加の E_RUNAWAY_QUERYオプション (要求オプションを設定し、シャッフル戦略を使用するようにクエリを変更することによって制限を増やすことを超える) は、サンプリングに切り替えることです。 次の 2 つのクエリは、サンプリングの実行方法を示しています。 1 つ目のクエリは、乱数ジェネレーターを使用した統計サンプリングです。 2 番目のクエリは確定的なサンプリングであり、データセットからいくつかの列 (通常は ID) をハッシュすることによって行われます。

T | where rand() < 0.1 | ...

T | where hash(UserId, 10) == 1 | ...

ノードあたりのメモリに対する制限

ノードあたりのクエリあたりの最大メモリは、"暴走" クエリから保護するために使用されるもう 1 つの制限です。 この制限は要求オプション max_memory_consumption_per_query_per_node で表され、特定のクエリに対して 1 つノードで使用できるメモリ量の上限が設定されます。

set max_memory_consumption_per_query_per_node=68719476736;
MyTable | ...

max_memory_consumption_per_query_per_node が複数回設定されている場合 (たとえばクライアント要求のプロパティと set ステートメントの両方を使用)、低い方の値が適用されます。

クエリで summarizejoin、または make-series 演算子が使用されている場合は、クエリのシャッフル戦略を使用して、1 台のコンピューターのメモリの負荷を軽減できます。

実行タイムアウトの制限

サーバー タイムアウトは、すべての要求に適用されるサービス側のタイムアウトです。 実行中の要求 (クエリと管理コマンド) のタイムアウトは、Kusto 内の複数のポイントで適用されます。

  • クライアント ライブラリ (使用されている場合)
  • 要求を受け入れるサービス エンドポイント
  • 要求を処理するサービス エンジン

既定では、クエリの場合はタイムアウトが 4 分、管理コマンドの場合は 10 分に設定されます。 この値は、必要に応じて増やすことができます (上限は 1 時間)。

  • さまざまなクライアント ツールで、グローバルな設定または接続ごとの設定の一部として、タイムアウトの変更がサポートされています。 たとえば、Kusto.Explorer で、[ツール]>[オプション]* >[接続]>[クエリ サーバーのタイムアウト] を使用します。
  • SDK は、プログラムによって servertimeout プロパティによるタイムアウトの設定をサポートします。 たとえば、.NET SDK では、クライアント要求のプロパティで、System.TimeSpan 型の値を設定してサポートされます。

タイムアウトに関する注意事項

  • クライアント側では、作成された要求から応答がクライアントに到着し始めるまでのタイムアウトが適用されます。 クライアントでペイロードの読み取りにかかる時間は、タイムアウトの一部として扱われません。 これは、呼び出し元がストリームからデータをプルする速度によって変わります。
  • また、クライアント側では、使用される実際のタイムアウト値は、ユーザーが要求したサーバー タイムアウト値よりもわずかに高くなります。 ネットワークの待機時間を考慮に入れるために、この差があります。
  • 最大許容要求タイムアウトを自動的に使用するには、クライアント要求プロパティ norequesttimeouttrue に設定します。

注意

Azure Data Explorer Web UI、Kusto.エクスプローラー、Kusto.Cli、Power BI、SDK の使用時にタイムアウトを設定する方法の詳細なガイドについては、「タイムアウト制限の設定」を参照してください。

クエリの CPU リソース使用率に対する制限

Kusto を使用すると、クエリを実行して、クラスターと同じ数の CPU リソースを使用できます。 複数のクエリが実行されている場合は、クエリ間で公平なラウンド ロビンが試行されます。 このメソッドを使用すると、クエリ定義関数に最適なパフォーマンスが得られます。 また、特定のクエリに使用される CPU リソースを制限する場合もあります。 たとえば、"バックグラウンド ジョブ" を実行すると、同時実行インライン クエリの優先度を高くするために、システムで許容される待機時間が長くなる可能性があります。

Kusto では、クエリの実行時に 2 つの 要求プロパティ を指定できます。 そのプロパティは、query_fanout_threads_percentquery_fanout_nodes_percent です。 どちらのプロパティも既定値は最大値 (100) の整数ですが、クエリによっては他の値に減らすこともできます。

1 つ目 query_fanout_threads_percent を使用すると、スレッドの使用に対するファンアウト係数を制御できます。 このプロパティが 100% に設定されている場合、クラスターによって各ノードにすべての CPU が割り当てられます。 たとえば、Azure D14 ノードにデプロイされたクラスター上の 16 個の CPU です。 このプロパティが 50% に設定されている場合は CPU の半分が使用されます。その他の値も同様です。 数値は CPU 全体に切り上げられるため、プロパティ値を 0 に設定しても問題ありません。

2 つ目の query_fanout_nodes_percent を使用すると、サブクエリの分散演算ごとに使用するクラスター内のクエリ ノード数を制御できます。 機能は同様です。

query_fanout_nodes_percent または query_fanout_threads_percent が複数回設定されている場合 (たとえばクライアント要求のプロパティと set ステートメントの両方を使用)、各プロパティの低い方の値が適用されます。

クエリの複雑さに対する制限

クエリの実行時に、クエリ テキストはクエリを表す関係演算子のツリーに変換されます。 ツリーの深さが内部しきい値を超えると、複雑すぎて処理できないクエリと見なされて失敗し、エラー コードが返されます。 このエラーは、関係演算子ツリーが制限を超えていることを示します。

次の例は、クエリがこの制限を超えて失敗する可能性がある一般的なクエリ パターンを示しています。

  • 一緒に連結される二項演算子の長いリスト。 例:
T 
| where Column == "value1" or 
        Column == "value2" or 
        .... or
        Column == "valueN"

この特定のケースでは、in() 演算子を使用してクエリを書き直してください。

T 
| where Column in ("value1", "value2".... "valueN")
  • スキーマ分析をあまりにも広範囲に実行している和集合演算子が含まれるクエリ。とりわけ、和集合の既定のフレーバーが "外側の" 和集合スキーマを返すことになっています (つまり、基礎となるテーブルのすべての列が出力に含まれます)。

この場合、クエリを見直し、クエリで使用されている列を減らすことをお勧めします。