パフォーマンス効率のベストプラクティス

この記事では、次のセクションに示すアーキテクチャの原則別に整理された 、パフォーマンス効率のベスト プラクティスについて説明します。

垂直スケーリング、水平スケーリング、および線形スケーラビリティ

ベスト プラクティスについて説明する前に、まず分散コンピューティングに関するいくつかの概念 (水平スケーリングと垂直スケーリング、線形スケーラビリティ) を見てみましょう。

  • 1 台のコンピューター (通常は CPU、メモリ、または GPU) のリソースを追加または削除することによる垂直スケーリング 。通常、これはワークロードを停止し、より大きなマシンに移動してから、再起動することを意味します。 垂直スケーリングには限界があります:より大きなマシンがないかもしれないか、次に大きなマシンの価格が法外に高いかもしれません。

  • 分散システムにノードを追加または削除することによる水平方向のスケーリング: 垂直方向のスケーリングの限界に達した場合、解決策は水平方向のスケーリングです。分散コンピューティングでは、複数のマシン (クラスターと呼ばれる) を備えたシステムを使用してワークロードを実行します。 これを可能にするには、Databricks レイクハウス、Apache Spark、Photon のエンジンによってサポートされるように、ワークロードを並列実行用に準備する必要があることを理解することが重要です。 これにより、リーズナブルな価格の複数のマシンを組み合わせて、より大きなコンピューティングシステムにすることができます。 さらに多くのコンピュート リソースが必要な場合、水平スケーリングによってクラスターにノードが追加され、不要になった時点でノードが削除されます。 技術的には制限はありませんが (負荷分散の複雑な部分は Spark エンジンが引き継ぎます)、ノードの数が多いと管理の複雑さが増加します。

  • 線形スケーラビリティーとは、システムにリソースを追加するときに、スループットと使用済みリソースの関係が線形になることを意味します。これは、並列タスクが独立している場合にのみ可能です。 そうでない場合は、さらに計算するために、あるノード セットの中間結果をクラスター内の別のノード セットで必要にします。 このノード間のデータ交換には、あるノード セットから別のノード セットにネットワーク経由で結果を転送することが含まれますが、これにはかなりの時間がかかります。 一般に、分散コンピューティングには、データの配布と交換を管理するためのオーバーヘッドが常にあります。 その結果、単一ノードで分析できる小さなデータセットのワークロードは、分散システムで実行するとさらに遅くなる可能性があります。 Databricksデータインテリジェンスプラットフォームは、ワークロード固有のニーズを満たす柔軟なコンピューティング (単一ノードおよび分散) を提供します。

パフォーマンスのためのワークロードの設計

データ取り込みとアクセスパターンを理解する

パフォーマンスの観点から見ると、"集計とポイント アクセス" や "スキャンと検索" などのデータ アクセス パターンは、データ サイズに応じて動作が異なります。 大きなファイルはスキャンクエリーに効率的であり、特定の行を見つけるために読み取る必要があるデータが少ないため、小さなファイルは検索に適しています。

インジェスト パターンでは、DML ステートメントを使用するのが一般的です。 DML ステートメントは、データがクラスター化されている場合に最もパフォーマンスが高く、データのセクションを分離するだけで済みます。 インジェスト時にデータをクラスター化して分離可能にすることが重要です: 自然な時間の並べ替え順序を維持し、取り込みターゲット テーブルにできるだけ多くのフィルターを適用することを検討してください。 追加専用および上書きインジェストのワークロードの場合、これは比較的安価な操作であるため、考慮することはあまりありません。

インジェストとアクセスのパターンは、多くの場合、明らかなデータ レイアウトとクラスターを指しています。 そうでない場合は、ビジネスにとって何がより重要かを決定し、その目標をより適切に解決する方法に偏ります。

有益な場合は並列計算を使用する

価値実現までの時間は、データを扱う際の重要な側面です。 多くのユースケースは1台のマシンに簡単に実装できますが(小さなデータ、少数の単純な計算ステップ)、多くの場合、次のようなユースケースが発生します。

  • 大規模なデータセットを処理する必要があります。

  • 複雑なアルゴリズムのために実行時間が長くなります。

  • 数百回と数千回繰り返す必要があります。

Databricks プラットフォームのクラスター環境は、これらのワークロードを効率的に分散するのに最適な環境です。 クラスターのすべてのノードにわたって SQL クエリを自動的に並列化し、同じことを実行するためのPythonおよびScala用のライブラリを提供します。 内部的には、Apache Spark と Photon のエンジンがクエリを分析し、並列実行の最適な方法を決定し、分散実行を回復力のある方法で管理します。

バッチタスクと同様に、構造化ストリーミングは ストリーミング ジョブをクラスター全体に分散して、最高のパフォーマンスを実現します。

並列コンピューティングを使用する最も簡単な方法の1つは Delta Live Tablesです。 SQL または Python でジョブのタスクと依存関係を宣言すると、Delta Live Tables が実行計画、効率的なインフラストラクチャのセットアップ、ジョブの実行、およびモニタリングを引き継ぎます。

データサイエンティストにとって、 pandas はPythonプログラミング言語用の使いやすいデータ構造とデータ分析ツールを提供するPythonパッケージです。 ただし、Pandasはビッグデータにスケールアウトしません。 Spark 上の Pandas API は、Apache Spark で動作する pandas と同等の APIs を提供することで、このギャップを埋めます。

さらに、プラットフォームには、 MLlibと呼ばれる機械学習用の並列アルゴリズムが付属しています。 マルチGPUやHorovod Runnerなどの分散ディープラーニングコンピュートを活用したすぐに使えるサポートです。 HorovodRunner: 分散型ディープラーニング with Horovod を参照してください。プラットフォームに付属している特定のライブラリは、大量に繰り返されるタスクをすべてのクラスターノードに分散させるのに役立ち、ほぼ直線的な方法で価値を下げるまでの時間を短縮します。 たとえば、機械学習における並列ハイパーパラメータ最適化のための Hyperopt

実行チェーン全体を分析

ほとんどのパイプラインまたは消費パターンは、システムのチェーンを使用します。 たとえば、BI ツールの場合、パフォーマンスはいくつかの要因の影響を受けます。

  • BI ツール自体。

  • BI ツールと SQL エンジンを接続するコネクタ。

  • BI ツールがクエリーを送信する SQL エンジン。

クラス最高のパフォーマンスを得るには、チェーン全体をアカウントに取り込み、最高のパフォーマンスが得られるように選択/調整する必要があります。

より大きなクラスターを優先する

大規模なクラスターを計画します (特にワークロードが直線的にスケーリングされる場合)。 その場合、ワークロードに大規模なクラスターを使用する方が、小規模なクラスターを使用するよりもコストがかかりません。 それはただ速いです。 重要なのは、ワークロードの長さだけクラスターをレンタルしていることです。 したがって、2 つのワーカー クラスターをスピンアップして 1 時間かかる場合は、それらのワーカーに対して 1 時間分の料金を支払うことになります。 同様に、4 ワーカー クラスターを起動して 30 分しかかからない場合 (ここでは線形スケーラビリティが作用します)、コストは同じです。 コストが非常に柔軟なSLAの主な推進力である場合、オートスケールクラスターはほとんどの場合最も安価になりますが、必ずしも最速ではありません。

ネイティブの Spark 操作を使用する

ユーザー定義関数 (UDF) は、Spark SQL の機能を拡張するための優れた方法です。 ただし、ネイティブ関数が存在する場合は、Python または Scala UDF を使用しないでください。

理由:

  • Python と Spark の間でデータを転送するには、シリアル化が必要です。 これにより、クエリーの速度が大幅に低下します。

  • プラットフォームにすでに存在する機能の実装とテストのためのより高い努力。

ネイティブ関数が欠落していて、Python UDF として実装する必要がある場合は、 Pandas UDF を使用します。 Apache Arrowは 、データがSparkとPythonの間を効率的に行き来することを保証します。

Photonを使用する

Photon はDatabricksのエンジンで、データ取り込み、ETL、ストリーミング、データサイエンス、インタラクティブクエリーなど、高速なクエリーパフォーマンスを低コストでデータレイク上で直接提供します。 PhotonはApache Spark APIsと互換性があるため、コードの変更やロックインなしで、電源を入れるのと同じくらい簡単に開始できます。

Photonは、既存のSQLおよび DataFrame API呼び出しをより高速に実行し、ワークロードあたりの総コストを削減する高性能ランタイムの一部です。 Photon は、Databricks SQLウェアハウスで既定で使用されます。

ハードウェアとワークロードの種類を理解する

すべてのクラウド VM が同じように作成されるわけではありません。 クラウドプロバイダーが提供するさまざまなマシンファミリーはすべて、問題になるほど異なっています。 RAMとコアという明らかな違いと、プロセッサの種類と世代、ネットワーク帯域幅の保証、ローカル高速ストレージとローカルディスクとリモートディスクの微妙な違いがあります。 「スポット」市場にも違いがあります。 ワークロードに最適な VM の種類を決定する前に、これらを理解する必要があります。

キャッシュを使用する

Databricks では、ディスク キャッシュと Spark キャッシュの 2 種類のキャッシュを使用できます。 各タイプの特徴は次のとおりです。

  • ディスクキャッシュを使用

    ディスク キャッシュ(以前は「 Deltaキャッシュ」として知られていました) は、仮想マシンのローカル ディスク ( SSDなど) にリモート データのコピーを保存します。 さまざまなクエリのパフォーマンスを向上させることができますが、任意のサブクエリの結果を格納するために使用することはできません。 ディスクキャッシュは、データファイルが作成または削除されたことを自動的に検出し、それに応じてその内容を更新します。 ディスク キャッシュを使用するための推奨される (そして最も簡単な) 方法は、クラスターを構成するときに SSD ボリュームを備えたワーカー タイプを選択することです。 このようなワーカーは、ディスク キャッシュ用に有効化および構成されています。

  • Spark キャッシュを避ける

    Spark キャッシュ (.persist().unpersist()を使用) には、サブクエリ データと、Parquet 以外の形式 (CSV、JSON、ORC など) で格納されたデータの結果を格納できます。ただし、クエリー内の間違った場所で使用すると、すべてのメモリを消費し、クエリーの速度が大幅に低下することさえあります。 経験則として、影響を正確に把握していない限り、Spark キャッシュは避けてください。 「Spark キャッシュ」を参照してください。

  • クエリー 結果キャッシュ

    SQLウェアハウスを介したすべてのクエリのクエリ結果のクラスタごとのキャッシュ。 クエリ結果のキャッシュの恩恵を受けるには、たとえば = NOW()のような述語を使用しない決定論的クエリに焦点を当てます。 クエリが決定的で、基になるデータがDelta形式で変更されていない場合、SQLウェアハウスはクエリ結果キャッシュから直接結果を返します。

  • Databricks SQL UI キャッシュ

    すべてのクエリーとダッシュボードのユーザーごとのキャッシュは、 Databricks SQL UI になります。

  • 予熱クラスター

圧縮を使用する

Databricks でDelta Lake を使用すると、テーブルからのクエリーの読み取り速度を向上させることができます。この速度を向上させる1つの方法は、小さなファイルを大きなファイルに結合することです。 圧縮をトリガーするには、OPTIMIZE コマンドを実行します。 「 Delta LakeでOPTIMIZEによりデータファイルを圧縮する」を参照してください。

自動最適化を使用して、小さなファイルを自動的に圧縮することもできます。 ファイルサイズの調整を検討するを参照してください。

データのスキップを使用する

データのスキップ: これを実現するために、Delta テーブルにデータを書き込むと、データ スキップ情報が自動的に収集されます (既定では、Databricks 上の Delta Lake は、テーブル スキーマで定義されている最初の 32 列の統計を収集します)。 Databricks 上の Delta Lake は、クエリ時にこの情報 (最小値と最大値) を利用して、クエリを高速化します。 「 Delta Lake のデータ スキップ」を参照してください。

最適な結果を得るには、 Z オーダー(関連情報を同じファイル セットに併置する手法) を適用します。 この共局所性は、Delta Lake データ スキップ アルゴリズムによって Databricks で自動的に使用されます。 この動作により、Databricks 上の Delta Lake が読み取る必要があるデータの量が大幅に減少します。

動的ファイルプルーニング: 動的ファイルプルーニング (DFP) を使用すると、Delta テーブル上の多くのクエリーのパフォーマンスを大幅に向上させることができます。 DFP は、パーティション分割されていないテーブルや、パーティション分割されていない列での結合に特に効率的です。

過剰なパーティション分割を避ける

以前は、パーティション分割がデータをスキップする最も一般的な方法でした。 ただし、パーティション分割は静的であり、ファイル システム階層として現れます。 アクセスパターンが時間の経過とともに変化する場合、パーティションを変更する簡単な方法はありません。 多くの場合、パーティション分割は過剰なパーティション分割につながります - つまり、ファイルが小さすぎるパーティションが多すぎるため、クエリーのパフォーマンスが低下します。 パーティションを参照してください。

それまでの間、パーティション分割よりもはるかに優れた選択肢は Z-ordering です。

ファイル サイズのチューニングを検討する

自動最適化 という用語は、設定によって制御される機能を説明するために使用されることがあります delta.autoCompactdelta.optimizeWrite。この用語は廃止され、各設定を個別に説明できるようになりました。 「 データ ファイルのサイズを制御するための Delta Lake の構成」を参照してください。

自動最適化は、次のシナリオで特に役立ちます。

  • 分単位の待機時間が許容されるストリーミングのユース ケース。

  • マージイントは、 Delta Lakeに書き込むための推奨される方法です。

  • CREATE TABLE AS SELECT または INSERT INTO は一般的に使用される操作です。

結合パフォーマンスの最適化

  • 範囲結合の最適化を検討してください。 範囲結合の最適化を参照してください。

    範囲結合は、間隔内の点または間隔のオーバーラップ条件を使用して 2 つのリレーションが結合される場合に発生します。 Databricks ランタイムの範囲結合最適化のサポートにより、クエリーのパフォーマンスが大幅に向上する可能性がありますが、慎重な手動チューニングが必要です。

  • スキュー結合の最適化を検討してください。

    データ スキューは、テーブルのデータがクラスター内のパーティション間で不均等に分散されている状態です。 データ スキューは、クエリー (特に結合を伴うクエリー) のパフォーマンスを大幅に低下させる可能性があります。 大きなテーブル間の結合にはデータのシャッフルが必要であり、スキューによってクラスター内の作業が極端に不均衡になる可能性があります。 クエリーが非常に少ないタスクを完了し滞っているように見える場合は、データスキューがクエリーに影響を与えている可能性があります。 スキューを改善するために、Databricks SQL の Delta Lake はクエリーでスキュー ヒントを受け入れます。 スキューヒントからの情報を使用して、 Databricks Runtime はデータスキューの影響を受けないより良いクエリプランを構築できます。 次の 2 つのオプションがあります。

テーブルの分析を実行してテーブル統計を収集する

テーブルの分析を実行して、クエリープランナーのテーブル全体の統計を収集します。 「テーブルの分析」を参照してください。

ANALYZE TABLE mytable COMPUTE STATISTICS FOR ALL COLUMNS;

この情報はメタストアに保持され、次の方法でクエリー オプティマイザーを支援します。

  • 適切な結合タイプの選択。

  • ハッシュ結合で正しいビルド側を選択する。

  • 多方向結合での結合順序の調整。

毎日 OPTIMIZE と一緒に実行する必要があり、5 TB <テーブルで推奨されます。 唯一の注意点は、分析テーブルはインクリメンタルではないということです。

開発範囲でのパフォーマンス テストの実行

本番運用データを表すデータのテスト

運用データ (読み取り専用) または同様のデータに対してパフォーマンス テストを実行します。 同様のデータを使用する場合、ボリューム、ファイル レイアウト、データ スキューなどの特性は、パフォーマンスに大きな影響を与えるため、運用データと同様である必要があります。

リソースの事前ウォーミングをアカウントに入れる

新しいクラスターの最初のクエリーは、他のすべてのクエリーよりも低速です。

  • 一般に、クラスター リソースは複数のレイヤーで初期化する必要があります。

  • キャッシュがセットアップの一部である場合、最初の実行でデータがキャッシュにあることが確認され、後続のジョブが高速化されます。

リソースを事前にウォーミングする (リソースを初期化してキャッシュを埋めるために特定のクエリーを実行する (たとえば、クラスターの再起動後) と、最初のクエリーのパフォーマンスが大幅に向上します。 そのため、さまざまなシナリオの動作を理解するには、最初の実行 (事前ウォーミングありと事前ウォーミングあり) と後続の実行のパフォーマンスをテストします。

ヒント

ダッシュボードの更新などの対話型ワークロードは、事前ウォーミングから大きなメリットを得ることができます。 ただし、これは、設計による読み込みが一度だけ実行されるジョブ クラスターには適用されません。

ボトルネックを特定する

ボトルネックは、運用環境の負荷が増加したときに全体的なパフォーマンスを低下させる可能性があるワークロード内の領域です。 設計時にこれらを特定し、より高いワークロードに対してテストすると、運用環境でワークロードを安定させるのに役立ちます。