クエリの最大メモリ使用量の制限

クエリはマルチスレッドで実行されます。つまり、各クエリに対して、Virtual DataPort がクエリで使用されているデータソースごとに対応するスレッドを 1 つずつ使用し、さらにソースから取得したデータを結合するスレッドを 1 つ使用します。

Virtual DataPort は、複数のクエリを同時に処理できるので、スワップを使用したとしても、クエリが使用するメモリ量がかなりのレベルまで増加する可能性があります。また、並列処理を使用しているので、同じクエリの複数の非ストリーミング操作を同時に実行できます。たとえば、4 つの異なるデータソースのビューを結合するクエリがあり、すべての結合はハッシュ実行メソッドを使用して実行される場合、最大 3 つの非ストリーミング操作がパラレルに実行できるので、全体的なメモリ消費量が増加します。

[Limit Query Memory Usage] パラメーターは、1 つのクエリが使用できるメモリ量に制限を設定することによって、この潜在的な問題を解決します。このパラメーターが有効かどうかを確認するには、[Server administration] を開いて [Memory usage] タブをクリックし、[Limit query memory usage] で [On] が選択されているかどうかを確認します。

この機能が有効な場合、実行エンジンは、クエリの実行プランを分析して、クエリトポロジーを前提としてパラレルに実行される非ストリーミング操作の最大数を検出します (この数は通常はプランの非ストリーミング操作の総数より少ない)。それらの演算子に割り当てられるスワップサイズの合計に、すべてのクエリにその複雑さに応じて必要な最小メモリを加算した値が [Maximum Query Size] で指定されている値よりも大きい場合、実行エンジンは、クエリを実行しても制限を超えないことを保証するために、自動的に [Maximum size in memory of each node] と [Maximum size in memory of intermediate results] の値を減らします。このプロパティの値の変更は、このクエリの実行に対してのみ適用され、ビュー、データベース、またはサーバーの設定を変更するものではありません。

一般に、クエリのメモリ使用量を制限することは、システムのリソースを独占する単一クエリが存在しないことが保証されるので、良い方法です。ただし、サーバーに使用可能な空きメモリが存在するにも関わらず、特定のクエリが少ないリソースで動作するように強制される可能性があることに注意してください。したがって、クエリが事前定義されており (このため、必要なメモリ量が急激に変化することがない)、同時性のレベルによってメモリの問題が発生しないことが保証されるようにスケジュールされているシナリオでは、この機能を無効にしてクエリのパフォーマンスを向上させられます。

[Maximum Query Size] パラメーターに割り当てる値は、以下の値に基づいて調整できます。

  1. 大量のメモリを使用する可能性があると考えられるクエリの予想される最大同時実行数 (ストリーミング操作のみを使用するクエリは、通常は非常に少ないメモリ量で動作することに注意する)

  2. 使用可能なメモリ (他のクエリおよび予想外のピークに割り当てるメモリは、常に実際のヒープサイズの 50 ~ 60% のみになるように検討する)

たとえば、Virtual DataPort が、データソースにプッシュダウンできない複数の非ストリーミング演算子 (ハッシュ結合、ハッシュグループ化) を使用する複雑なクエリを最大 20 個同時に実行することが予想され、JVM に 8 GB のヒープサイズが実際に確保されている場合、このパラメーターの合理的な値は 200 MB です。

ただし、クエリが使用可能なメモリを増やすことが、常にパフォーマンス向上につながるわけではありません。たとえば、大量のメモリを使用するクエリは (たとえ使用可能なメモリ領域に収まるとしても)、JVM で大量のガベージコレクションサイクルを発生させる可能性があります。また、メモリが実際に確保されていない仮想マシン上でホストオペレーティングシステムを実行している場合 (どんな場合でも避ける必要がある不適切な習慣)、理論的に「使用可能な」メモリが「実際に存在しない」可能性があり、それを獲得するプロセスが高コストになることがあります。

一般に、クエリが使用するメモリ量が少ないことが保証されると、アプリケーションのパフォーマンスと安定性が大幅に向上します。それを実践しないのは、利点が明確で、実証されている場合のみにする必要があります。これは、JVM のヒープサイズに関係なく、この制限を非常に大きい値 (たとえば 1 GB 以上) に設定することを推奨しない理由でもあります。

Virtual DataPort は、クエリが以下の条件のいずれかを満たす場合、クエリあたりのメモリ制限が守られることを保証しません。

  1. クエリの WHERE 句にサブクエリが存在する。

  2. クエリに DISTINCT 修飾子を使用する集計関数 (例: SELECT COUNT ( DISTINCT field1 ) ) FROM ...) が存在する。集計関数の外部で DISTINCT を使用するクエリ (例: SELECT DISTINCT field1 FROM ...) は、この条件には含まれません。