I/O が少ない低速 Spark ステージ
I/O があまりない低速ステージは、次のことが原因で発生する可能性があります。
- 多数の小さなファイルを読み取る
- 多数の小さなファイルを書き込む
- 低速な UDF
- デカルト結合
- 分解結合
これらの問題のほとんどは、SQL DAG を使用して特定できます。
SQL DAG を開く
SQL DAG を開くには、ジョブのページの上部までスクロールし、[関連付けられた SQL クエリ] をクリックします。
これで DAG が表示されます。 そうでない場合は、少しスクロールすると表示されます。
先に進む前に、DAG と時間がかかっている場所について理解しておく必要があります。 DAG 内には、役立つ時間情報があるノードと、そうでないノードがあります。 たとえば、このブロックには 2.1 分かかり、ステージ ID も提供されています。
このノードは、1.4 分かかったことを確認するには開く必要があります。
これらの時間は累積されるため、これはクロック時間ではなく、すべてのタスクに費やされた合計時間です。 しかし、それらはクロック時間とコストと相関しているので、依然として非常に便利です。
DAG 内のどこで時間が費やされているかをよく理解しておくと役立ちます。
多数の小さなファイルを読み取る
スキャン演算子の 1 つに多くの時間がかかっている場合は、それを開いて、読み取られたファイルの数を探します。
何万ものファイルを読み取っている場合は、小さなファイルの問題が発生している可能性があります。 ファイルは 8 MB を下回らないようにする必要があります。 小さなファイルの問題は、多すぎる列またはカーディナリティの高い列に対するパーティション分割が原因で発生することがよくあります。
運が良ければ、OPTIMIZE を実行するだけで済むかもしれません。 いずれにしても、ファイル レイアウトを再考する必要があります。
多数の小さなファイルを書き込む
書き込みに時間がかかっている場合は、それを開き、ファイルの数と書き込まれたデータの量を探します。
何万ものファイルを書き込んでいる場合は、小さなファイルの問題が発生している可能性があります。 ファイルは 8 MB を下回らないようにする必要があります。 小さなファイルの問題は、多すぎる列またはカーディナリティの高い列に対するパーティション分割が原因で発生することがよくあります。 ファイル レイアウトを再考するか、最適化された書き込みを有効にする必要があります。
低速な UDF
UDF があることがわかっている場合、または DAG に次のような情報が表示された場合は、低速な UDF が問題を起こしている可能性があります。
この問題に苦しんでいると思う場合は、UDF をコメント アウトして、パイプラインの速度に与える影響を確認してみてください。 UDF が実際に時間を消費している場合は、ネイティブ関数を使用して UDF を書き換えるのが最善の策です。 それが不可能な場合は、UDF を実行しているステージ内のタスクの数を検討してください。 クラスターのコア数より少ない場合は、UDF を使用する前にデータフレームに対し repartition()
を使用します。
(df
.repartition(num_cores)
.withColumn('new_col', udf(...))
)
UDF では、メモリの問題が発生する可能性もあります。 各タスクは、そのパーティション内のすべてのデータをメモリに読み込む必要がある可能性があることを考慮してください。 このデータが大きすぎると、非常に遅くなったり不安定になったりする可能性があります。 再パーティション分割では、各タスクを小さくすることで、この問題を解決することもできます。
デカルト結合
DAG にデカルト結合または入れ子になったループ結合が表示される場合は、これらの結合が非常にコストがかかることを知っている必要があります。 これが意図した内容であることを確認し、別の方法があるかどうかを確認します。
分解結合 (explode)
いくつかの行がノードに入り、さらに多数がノードから出てくる場合は、分解結合 explode() が問題である可能性があります。
explode の詳細については、Databricks の最適化ガイドを参照してください。