メインコンテンツまでスキップ

並列度チューニング

概要

Dorisクエリは、MPP(Massively Parallel Processing)フレームワークで実行され、各クエリは複数のBE(Backend Executors)間で並列実行されます。一方、単一のBE内では、クエリ実行効率を向上させるためにマルチスレッド並列アプローチが採用されています。現在、クエリ、DML(Data Manipulation Language)、DDL(Data Definition Language)を含むすべてのタイプのステートメントが並列実行をサポートしています。

単一のBE内の並列度の制御パラメータはparallel_pipeline_task_numで、これは実行中に単一のFragmentが使用するワーキングタスクの数を指します。実際の本番シナリオでは、不適切な並列度設定によりパフォーマンスの問題が発生する場合があります。以下の例では、並列度を最適化するケースを示しています。

並列度チューニングの原則

parallel_pipeline_task_numを設定する目的は、マルチコアリソースを十分に活用し、クエリレイテンシを削減することです。ただし、マルチコア並列実行を有効にするために、通常はいくつかのデータshuffleオペレータと複数のスレッド間の同期ロジックが導入され、これにより不要なリソースの浪費につながる場合もあります。

Dorisのデフォルト値は0で、これはBEのCPUコア数の半分です。この値は、単一クエリと並行処理の両方のリソース使用率を考慮しており、通常はユーザーが調整に介入する必要はありません。パフォーマンスボトルネックがある場合は、以下の例を参考に必要な調整を行ってください。Dorisは適応戦略を継続的に改善しており、通常は特定のシナリオやSQLレベルで必要な調整を行うことが推奨されます。

BEが16個のCPUコアを持っていると仮定します:

  1. 単一テーブルでの単純な操作(単一テーブルのポイントクエリ、少量のデータを取得するWHERE句スキャン、少量のデータのLIMIT、またはマテリアライズドビューのヒットなど)の場合、並列度は1に設定できます

    説明:単一テーブルでの単純な操作には、1つのFragmentのみが含まれます。このようなクエリのボトルネックは通常、データのスキャンと処理にあります。データスキャンスレッドとクエリ実行スレッドは分離されており、データスキャンスレッドは適応的に並列スキャンを実行します。ここでのボトルネックはクエリスレッドではないため、並列度を直接1に設定できます。

  2. 2つのテーブルのJOINや集計クエリを含むクエリで、データ量が大きく、CPU集約型のクエリであることが確認されている場合、並列度は16に設定できます

    説明:2つのテーブルのJOINや集約クエリなど、データ計算集約型のクエリでは、CPUが十分に活用されていない場合、デフォルト値をベースに並列度を増やして、Pipelineエンジンの並列機能を活用し、計算にCPUリソースを十分に活用することを検討してください。各PipelineTaskが割り当てられたCPUリソースを最大限に活用できるとは限りません。したがって、並列度を適切に調整、例えば16に設定することで、CPUをより有効活用できます。ただし、並列度を無制限に増やすべきではありません。48に設定しても実質的な効果はもたらされず、代わりにスレッドスケジューリングオーバーヘッドとフレームワークスケジューリングオーバーヘッドが増加します。

  3. ストレステストシナリオで、ストレステスト内の複数のクエリがCPUを十分に活用できる場合、並列度は1に設定できます

    説明:ストレステストシナリオでは、十分なクエリタスクがあります。過度な並列化もスレッドスケジューリングオーバーヘッドとフレームワークスケジューリングオーバーヘッドをもたらします。この場合、1に設定する方が合理的です。

  4. 複雑なクエリの場合、Profileとマシン負荷に基づいて並列度を柔軟に調整する必要があります。ここでは、デフォルト値の使用が推奨されます。適していない場合は、4-2-1の段階的調整を試すことができ、クエリパフォーマンスとマシン負荷を観察する必要があります。

並列度チューニングの方法

Dorisでは、ユーザーがクエリの並列度を手動で指定して、クエリ実行中の並列実行効率を調整できます。

SQLレベルの調整

SQL HINTを使用して単一のSQLステートメントの並列度を指定します。これにより、異なるSQLステートメントの並列度を柔軟に制御し、最適な実行結果を実現できます。

select /*+SET_VAR(parallel_pipeline_task_num=8)*/ * from nation, lineitem where lineitem.l_suppkey = nation.n_nationkey
select /*+SET_VAR(parallel_pipeline_task_num=8,runtime_filter_mode=global)*/ * from nation, lineitem where lineitem.l_suppkey = nation.n_nationkey

セッションレベル調整

セッション変数を通じてセッションレベルでparallelismを調整します。セッション内のすべてのクエリステートメントは、指定されたparallelismで実行されます。単一行のSQLクエリでもこのparallelismが使用されるため、パフォーマンスの低下を招く可能性があることにご注意ください。

set parallel_pipeline_task_num = 8;

グローバル調整

グローバル調整が必要な場合、通常はCPU使用率の調整を含みますが、並列度をグローバルに設定できます。

set global parallel_pipeline_task_num = 8;

Tabletと並列性

バージョン2.1以降、Dorisは並列性をtablet数から切り離すことをサポートしています。

以前のバージョンでは、並列性はクエリに関与するtablet数を超えることができませんでした。例えば、クエリが5つのtabletに関与する場合、最大スキャン並行性は5のみでした。これにより、一部の大きなtabletが並行して読み取られることが妨げられる可能性がありました。

新しいバージョンでは、Dorisはシャード内での並行読み取りをサポートしています。この機能は自動的に有効になり、ユーザー設定は不要です。

この機能はDuplicateおよびUnique Key Merge-On-Writeテーブルモデルのみをサポートしていることに注意してください。AggregateおよびUnique Key Merge-On-Readモデルには適用されません。これら2つのモデルでは、クエリ並列性は依然としてtablet数によって制約されます。

ベストプラクティス

ケース1: 高並行圧力シナリオにおいて高並列性が高CPU使用率を引き起こす場合

オンラインで高CPU使用率が観察され、一部の低レイテンシクエリのパフォーマンスに影響する場合は、CPU使用率を削減するためにクエリ並列性の調整を検討してください。Dorisの設計哲学は、可能な限り迅速にクエリ結果を取得するためにより多くのリソースを使用することを優先するため、オンラインリソースが逼迫している一部のシナリオでは、これが悪いパフォーマンスにつながる可能性があります。したがって、並列性を適切に調整することで、限られたリソース下でのクエリの全体的な安定性と効率を向上させることができます。

並列性をデフォルト値の0(CPUコア数の半分)から4に設定します:

set global parallel_pipeline_task_num = 4;

グローバル設定後、現在の接続と新しい接続に対して効果が発揮されます。既存の他の接続は影響を受けません。即座にグローバルな効果が必要な場合は、FE(Frontend)を再起動することができます。調整後、CPU使用率は以前のピーク値の60%まで削減され、一部の低レイテンシクエリへの影響を軽減します。

ケース2:並列性を向上させてCPUをさらに活用しクエリを加速する

Dorisの現在のデフォルトの並列性はCPUコア数の半分であり、一部の計算集約的なシナリオでは、クエリ加速のためにCPUを十分に活用できません。

select sum(if(t2.value is null, 0, 1)) exist_value, sum(if(t2.value is null, 1, 0)) no_exist_value
from t1 left join t2 on t1.key = t2.key;

左のテーブルに20億行、右のテーブルに500万行があるシナリオでは、上記のSQLの実行に28秒かかります。Profileを確認してください:

HASH_JOIN_OPERATOR (id=3, nereids_id=448):
- PlanInfo
- join op: LEFT OUTER JOIN(BROADCAST)[]
- equal join conjunct: (value = value)
- cardinality=2,462,330,332
- vec output tuple id: 5
- output tuple id: 5
- vIntermediate tuple ids: 4
- hash output slot ids: 16
- projections: value
- project output tuple id: 5
- BlocksProduced: sum 360.099K (360099), avg 45.012K (45012), max 45.014K (45014), min 45.011K (45011)
- CloseTime: avg 8.44us, max 13.327us, min 5.574us
- ExecTime: avg 26sec153ms, max 26sec261ms, min 26sec33ms
- InitTime: avg 7.122us, max 13.395us, min 4.541us
- MemoryUsage: sum, avg, max, min
- PeakMemoryUsage: sum 1.16 MB, avg 148.00 KB, max 148.00 KB, min 148.00 KB
- ProbeKeyArena: sum 1.16 MB, avg 148.00 KB, max 148.00 KB, min 148.00 KB
- OpenTime: avg 2.967us, max 4.120us, min 1.562us
- ProbeRows: sum 1.4662330332B (1462330332), avg 182.791291M (182791291), max 182.811875M (182811875), min 182.782658M (182782658)
- ProjectionTime: avg 165.392ms, max 169.762ms, min 161.727ms
- RowsProduced: sum 1.462330332B (1462330332), avg 182.791291M (182791291), max 182.811875M (182811875), min 182.782658M (182782658)

ここでの主な時間消費部分:ExecTime: avg 26sec153ms, max 26sec261ms, min 26sec33msはすべてJoin operatorで発生し、処理されるデータの総量:ProbeRows: sum 1.4662330332Bは14億で、これは典型的なCPU集約型の計算シナリオです。マシンの監視を観察すると、CPUリソースが完全に活用されておらず、CPU使用率が60%であることがわかります。この時点で、並列度を増加させてアイドル状態のCPUリソースをさらに活用し、高速化を図ることを検討します。

並列度を以下のように設定します:

set parallel_pipeline_task_num = 16;

クエリ実行時間は28秒から19秒に短縮され、CPU使用率は60%から90%に向上しました。

概要

通常、ユーザーはクエリ並列度を調整する必要はありません。調整が必要な場合は、以下の点に注意してください:

  1. CPU使用率から始めることを推奨します。PROFILEツールの出力を通じてCPUボトルネックかどうかを観察し、並列度に対して合理的な修正を行うよう試してください。
  2. 単一のSQLを調整することは比較的安全です。過度に積極的なグローバル修正は行わないようにしてください。