翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
パフォーマンス効率の柱
AWS Well-Architected フレームワークのパフォーマンス効率の柱は、データの取り込みまたはクエリ中にパフォーマンスを最適化する方法に焦点を当てています。パフォーマンスの最適化は、以下の段階的かつ継続的なプロセスです。
-
ビジネス要件の確認
-
ワークロードのパフォーマンスの測定
-
パフォーマンスの低いコンポーネントを特定する
-
ビジネスニーズに合わせてコンポーネントを調整する
パフォーマンス効率の柱は、使用する適切なグラフデータモデルとクエリ言語を特定するのに役立つユースケース固有のガイドラインを提供します。また、Amazon Neptune にデータを取り込んで Amazon Neptune からデータを使用するときに従うべきベストプラクティスも含まれています。
パフォーマンス効率の柱は、次の主要分野に焦点を当てています。
-
グラフモデリング
-
クエリの最適化
-
クラスターの適切なサイジング
-
書き込みの最適化
グラフモデリングを理解する
ラベル付きプロパティグラフ (LPG) モデルとリソース記述フレームワーク (RDF) モデルの違いを理解します。ほとんどの場合、これは優先されます。ただし、1 つのモデルが他のモデルよりも適しているユースケースがいくつかあります。グラフ内の 2 つのノードを接続するパスに関する知識が必要な場合は、LPG を選択します。Neptune クラスターまたは他のグラフトリプルストア間でデータをフェデレーションする場合は、RDF を選択します。
Software as a Service (SaaS) アプリケーションまたはマルチテナンシーを必要とするアプリケーションを構築する場合は、クラスターごとに 1 つのテナントを持つのではなく、データモデルにテナントの論理的な分離を組み込むことを検討してください。このタイプの設計を実現するには、ラベルへの顧客識別子の付加や、テナント識別子を表すプロパティキーと値のペアの追加など、SPARQL の名前付きグラフとラベル付け戦略を使用できます。論理的な分離を維持するために、クライアントレイヤーがこれらの値を挿入していることを確認します。
クエリのパフォーマンスは、クエリの処理で評価する必要があるグラフオブジェクト (ノード、エッジ、プロパティ) の数によって異なります。そのため、グラフモデルはアプリケーションのパフォーマンスに大きな影響を与える可能性があります。可能な限り詳細なラベルを使用し、パスの判定またはフィルタリングに必要なプロパティのみを保存します。より高いパフォーマンスを実現するには、要約ノードの作成や一般的なパスを接続するより直接的なエッジの作成など、グラフの一部を事前に計算することを検討してください。
同じラベルを持つエッジ数が異常に多いノード間を移動しないようにします。このようなノードには多くの場合、数千のエッジがあります (ほとんどのノードのエッジカウントは数十です)。その結果、コンピューティングとデータの複雑さが大幅に高まります。これらのノードは、一部のクエリパターンでは問題にならない場合がありますが、特に中間ステップとしてノード間を移動する場合は、それを回避するためにデータを異なる方法でモデル化することをお勧めします。スロークエリログを使用して、これらのノード間を移動するクエリを識別できます。特にデバッグモードを使用する場合、平均クエリパターンよりもレイテンシーとデータアクセスメトリクスがはるかに高くなります。
Neptune を使用して IDsランダムな GUID 値を割り当てずに、ユースケースでサポートされている場合は、ノードとエッジに決定的なノード IDs を使用します。ID によるノードへのアクセスが最も効率的な方法です。
クエリを最適化する
openCypher 言語と Gremlin 言語は、LPG モデルで互換的に使用できます。パフォーマンスが最大の懸念事項である場合は、2 つの言語を同じ意味で使用することを検討してください。1 つの言語は特定のクエリパターンで他の言語よりもパフォーマンスが良い可能性があるためです。
Neptune は代替クエリエンジン (DFE) に変換中です。openCypher は DFE でのみ実行されますが、オプションでクエリ注釈を使用して Gremlin クエリと SPARQL クエリの両方を DFE で実行するように設定できます。DFE を有効にしてクエリをテストし、DFE を使用しない場合はクエリパターンのパフォーマンスを比較することを検討してください。
Neptune は、グラフ全体を評価する分析クエリではなく、単一ノードまたは一連のノードから開始してそこからファンアウトするトランザクションタイプのクエリに最適化されています。分析クエリワークロードでは、AWS SDK for Pandas
モデルとクエリの非効率性とボトルネックを特定するには、各クエリ言語の profile
および explain
APIs を使用して、クエリプランとクエリメトリクスの詳細な説明を取得します。詳細については、「Gremlin profile」、openCypher explain」、および「SPARQL explain」を参照してください。
クエリパターンを理解します。グラフ内の個別のエッジの数が大きくなると、デフォルトの Neptune アクセス戦略が非効率になる可能性があります。以下のクエリは、非常に非効率になる可能性があります。
-
エッジラベルが指定されていない場合にエッジをまたいで後方に移動するクエリ。
-
Gremlin など、内部
.both()
的に同じパターンを使用する句、または任意の言語でノードを削除する句 (ラベルを知らずに受信エッジを削除する必要があります)。 -
プロパティラベルを指定せずにプロパティ値にアクセスするクエリ。これらのクエリは非常に非効率になる可能性があります。これが使用パターンと一致する場合は、OSGP インデックス (オブジェクト、サブジェクト、グラフ、述語) を有効にすることを検討してください。
スロークエリログ記録を使用して、スロークエリを識別します。クエリが遅いのは、クエリプランが最適化されていないか、インデックスルックアップが不必要に多数あることが原因で、I/O コストが増加する可能性があります。Gremlin、SPARQL、または openCypher の Neptune explain および profile エンドポイントは、これらのクエリが遅い理由を理解するのに役立ちます。原因には次のようなものがあります。
-
グラフ内の平均ノードと比較してエッジ数が異常に多いノード (例えば、数千と数十) では、計算が複雑になり、レイテンシーが長くなり、リソースの消費が増加する可能性があります。これらのノードが正しくモデル化されているかどうか、またはトラバースする必要があるエッジの数を減らすためにアクセスパターンを改善できるかどうかを決定します。
-
最適化されていないクエリには、特定のステップが最適化されていないという警告が含まれます。これらのクエリを書き換えて最適化されたステップを使用すると、パフォーマンスが向上する可能性があります。
-
フィルターが重複すると、不要なインデックスルックアップが発生する可能性があります。同様に、冗長パターンは、クエリを改善することで最適化できるインデックスルックアップの重複を引き起こす可能性があります (プロファイル出力
Index Operations - Duplication ratio
の を参照)。 -
Gremlin などの一部の言語では、厳密に型指定された数値がなく、代わりに型昇格を使用します。例えば、値が 55 の場合、Neptune は整数、長整数、浮動小数点数、および 55 に相当するその他の数値型である値を検索します。これにより、追加のオペレーションが発生します。タイプが事前に一致することがわかっている場合は、クエリヒントを使用してこれを回避できます。
-
グラフモデルはパフォーマンスに大きな影響を与える可能性があります。より詳細なラベルを使用するか、マルチホップ線形パスへのショートカットを事前に計算して、評価する必要があるオブジェクトの数を減らすことを検討してください。
クエリの最適化だけではパフォーマンス要件を満たすことができない場合は、Neptune でさまざまなキャッシュ手法
適切なサイズのクラスター
同時実行とスループットの要件に合わせてクラスターのサイズを設定します。クラスター内の各インスタンスで処理できる同時クエリの数は、そのインスタンスの仮想 CPUs (vCPUs) の数の 2 倍に等しくなります。すべてのワーカースレッドが占有されている間に到着する追加のクエリは、サーバー側のキューに入れられます。これらのクエリは、ワーカースレッドが利用可能になったときにfirst-in-first-out (FIFO) ベースで処理されます。MainRequestQueuePendingRequests
Amazon CloudWatch メトリクスには、各インスタンスの現在のキューの深さが表示されます。この値が頻繁に 0 を超える場合は、より多くの vCPU を持つインスタンスを選択することを検討してください。 vCPUs キューの深さが 8,192 を超えると、Neptune はThrottlingException
エラーを返します。
各インスタンスの RAM の約 65% がバッファキャッシュ用に予約されています。バッファキャッシュは、作業データセット (グラフ全体ではなく、クエリ対象のデータのみ) を保持します。ストレージではなくバッファキャッシュから取得されるデータの割合を確認するには、CloudWatch メトリクス をモニタリングしますBufferCacheHitRatio
。このメトリクスが 99.9% を下回ることがよくある場合は、より多くのメモリを持つインスタンスを試して、レイテンシーと I/O コストを削減するかどうかを検討してください。
リードレプリカは、ライターインスタンスと同じサイズである必要はありません。ただし、書き込みワークロードが多いと、レプリケーションに追いつくことができないため、レプリカが小さくなり、再起動する可能性があります。したがって、レプリカをライターインスタンスと同じかそれ以上にすることをお勧めします。
リードレプリカに Auto Scaling を使用する場合は、新しいリードレプリカをオンラインにするまでに最大 15 分かかる場合があることに注意してください。クライアントトラフィックが迅速かつ予測可能な方法で増加する場合は、スケジュールされたスケーリングを使用して、その初期化時間を考慮してリードレプリカの最小数を高く設定することを検討してください。
サーバーレスインスタンスは、いくつかの異なるユースケースとワークロードをサポートしています。以下のシナリオでは、サーバーレスのオーバープロビジョニングされたインスタンスを検討してください。
-
ワークロードは 1 日を通して頻繁に変動します。
-
新しいアプリケーションを作成し、ワークロードのサイズが不明な場合。
-
開発とテストを実行している。
サーバーレスインスタンスは、同等のプロビジョニングされたインスタンスよりも RAM の GB 単位でコストがかかることに注意してください。各サーバーレスインスタンスは、2 GB の RAM と、関連する vCPU およびネットワークで構成されます。オプション間でコスト分析を実行して、予想外の請求を回避します。一般的に、1 日に数時間しかワークロードが非常に重く、残りの時間はほぼゼロである場合、またはワークロードが 1 日を通じて大幅に変動する場合にのみ、サーバーレスでコスト削減を達成できます。
書き込みの最適化
書き込みを最適化するには、次の点を考慮してください。
-
Neptune Bulk Loader は、最初にデータベースをロードしたり、既存のデータに追加したりするのに最適な方法です。Neptune ローダーはトランザクションではないため、データを削除できないため、これらが要件である場合は使用しないでください。
-
トランザクションの更新は、サポートされているクエリ言語を使用して行うことができます。書き込み I/O オペレーションを最適化するには、コミットごとに 50~100 個のオブジェクトのバッチでデータを書き込みます。オブジェクトは、LPG のノードまたはエッジ、または RDF のトリプルストアまたはクワッド上のノード、エッジ、またはプロパティです。
-
すべての Neptune 書き込みオペレーションは、接続ごとにシングルスレッドです。Neptune に大量のデータを送信するときは、それぞれがデータを書き込む複数の並列接続を持つことを検討してください。Neptune でプロビジョニングされたインスタンスを選択すると、インスタンスサイズは多数の vCPUs。Neptune はインスタンス上の vCPU ごとに 2 つのデータベーススレッドを作成するため、最適な並列化をテストするときに vCPUs の数の 2 倍から開始します。 サーバーレスインスタンスは、4 NCU ごとに約 1 の速度で vCPUs の数をスケーリングします。 NCUs
-
1 つの接続だけがいつでもデータを書き込んでいる場合でも、すべての書き込みプロセス中に ConcurrentModificationExceptions を計画し、効率的に処理します。
ConcurrentModificationExceptions
発生時の信頼性を考慮してクライアントを設計します。 -
すべてのデータを削除する場合は、同時削除クエリを発行するのではなく、高速リセット API を使用することを検討してください。後者では、前者と比較してはるかに時間がかかり、かなりの I/O コストが発生します。
-
ほとんどのデータを削除する場合は、neptune-export を使用して新しいクラスター
にデータをロードすることで、保持するデータをエクスポートすることを検討してください。次に、元のクラスターを削除します。