OpenSearchCon North America 2025のセッション「Capacity Planning, and Scaling/Optimization for Vector Workloads」をまとめます。

スピーカー

このセッションは、Amazon Web ServicesでAmazon OpenSearch ServiceのDirector of Solutions Architectureを務めるJon Handler氏によって行われました。
Handler氏はカリフォルニア州パロアルトを拠点に活動しており、OpenSearchとAmazon OpenSearch Serviceを専門として、ベクトル検索、サーチ、ログ分析のワークロードをAWSクラウドに移行しようとしている顧客を支援しています。AWSに入社する前は、4年間にわたって大規模なeコマース検索エンジンの開発に携わっていました。
学歴としては、ペンシルベニア大学で学士号を取得し、ノースウェスタン大学でコンピュータサイエンスと人工知能の修士号および博士号を取得しています。
OpenSearchの役割

私は多くの顧客とベクトルワークロードに取り組んでいます。今日は、OpenSearchのベクトルワークロードのストレージを最適化し、適切にデプロイするためのヒントやトリックをいくつかご紹介できればと思います。
まず、OpenSearchとは何かというところから説明を始めます。情報検索とは、関連する情報を見つけてアクセスするプロセスです。このプロセスにおいて、OpenSearchは重要な役割を果たしています。
一方には情報を求める人がいて、もう一方には膨大な知識の塊が存在します。OpenSearchは、これらの間に立って、人々の情報ニーズと保存されている知識を結びつける仲介役として機能します。OpenSearchは単なる検索エンジンではなく、検索、ベクトルデータベース、ログ分析スイートとして、OpenSearchプロジェクトをベースに構築されています。語彙検索とセマンティック検索の両方を提供し、AIエージェントやRetrieval-Augmented Generation(RAG)のための知識ベースとしても機能します。
全文検索

皆さんもご存知のように、過去5年ほど前までは、全文検索が主な方法でした。
画像は「マイク付きゲーミングヘッドセット」を検索した例です。下のアイテムは多くのマッチがありますが、これが見つけたいものなのかは微妙なところです。
セマンティック検索の仕組み

そこに埋め込みモデルが登場しました。埋め込みモデルはテキストを入力として受け取り、ベクトルを生成します。ベクトルという言葉はよく使われますが、実際にベクトルがどのようなものかを見せることは少ないので、ここで1500次元ベクトルの一部をお見せします。これはdenceベクトルで、大きな配列に格納された多数の数値の集まりです。
私たちが扱うのは多次元空間です。ここでお見せしているのは約20,000点の投影図で、これらはすべてそうしたベクトルから取得したものです。概念的に2次元に投影して視覚化していますが、重要なのは、そこに相関関係が学習されているということです。バックプロパゲーションと埋め込みモデルによって、テキスト入力間の相関関係が学習され、ベクトルマッチングで取得できるようにこの空間に配置されるのです。

セマンティック検索とは、ベクトルをマッチングする手段です。まずクエリのベクトル埋め込みを作成します。図の中央にかなり大きな点が見えますが、これがクエリを表しています。
基本的な考え方は、この広い空間内で距離に基づいて検索結果を取得することです。クエリから非常に近い位置にあるベクトルは類似していると判断して取得し、遠い位置にあるものは類似していないと判断して取得しません。これがセマンティック検索とベクトルマッチングを行う際にOpenSearchが達成しようとしていることの核心です。
ベクトル検索のユースケース

OpenSearchはベクトルデータベースとしていくつかの主要なユースケースを持っています。
最初のユースケースはAIを活用した検索です。ベクトルを保存し、ベクトルクエリにマッチさせ、Exact kNNまたは近似kNNを使用します。さらにフィルタリングを実行し、ハイブリッドクエリを実行して情報を取得できます。
2番目のユースケースはナレッジベースです。検索拡張生成(RAG)や会話型検索について話しますが、OpenSearchは、ユーザーとチャットしているアプリケーション、またはアプリケーションとチャットしているユーザーが正しい答えを得られるように、そして右側で要約しているLLMが誤った情報を送信しないように、正確な情報を提供する役割を果たします。
3番目のエージェント検索では、OpenSearch内にエージェントフレームワークがあり、LLMに接続して、OpenSearchを含む他のデータソースの上に推論、計画、検索を行い、そのデータを取り戻す機能を提供します。
スケーリングを考える基礎知識
スケーリングの要素

今日のトピックはスケーリングと最適化についてです。OpenSearchでベクトルを扱う際に検討すべき主要なワークロードを理解したところで、OpenSearchクラスターにデプロイするリソース全体にベクトルワークロードがどのように分散されるか、そのスケールに関するドライバーについて説明します。
最初はCPUです。CPUは当然リクエスト処理に関わります。OpenSearchにリクエストを送信すると、それはシャード全体に分散され、各シャードが処理を行います。ワークロードを駆動するのに十分なCPUがあるよう、シャードとCPUの比率を慎重に最適化する必要があります。ベクトルワークロードの場合、バックグラウンドタスクは純粋なテキストワークロードよりも少し重くなる場合があります。後で説明しますが、一部の近似メソッドでは、インデックス作成時間とマージ時間により多くのCPUを必要とする作業があります。
次にJavaヒープです。インデックス作成中、ワークロードはヒープも駆動します。検索中、特に集計などの一時的な構造を処理する場合はヒープについて考慮する必要がありますが、ベクトルではそれほど重要ではありません。
メモリはベクトルがかなり重要な役割を果たす場所です。Luceneは検索を高速化するためにオフヒープメモリを使用し、ベクトルもオフヒープメモリに存在します。これについては後で詳しく説明します。OpenSearch内には、ヒープとオフヒープの比率を設定できるパラメーターがあり、ベクトルワークロードを実行する場合はオフヒープに傾けるべきです。
(注:Amazon OpenSearch Serviceでは、ヒープはインスタンスRAMの半分(最大32 GiB)となり、残りがオフヒープとなります)
最後はストレージです。インデックスデータはディスクに存在し、ストレージは検索とインデックス作成のスループットに影響します。SSDは高速な検索スループットと高速なインデックス作成スループットを提供し、検索ユースケースには役立ちますが、ログユースケースにはそれほどではありません。これらが検討すべき主要なリソースです。
インデックスの構造

インデックスはデータの保存先です。インデックスにはすべての検索ドキュメントが保持されます。これらはクラスターのテナントのようなものです。
各インデックス内には、Lucene構造のセグメントがあります。これらのセグメントはインデックスの一部であり、クエリはそれらすべてに対して実行されなければなりません。
シャードと並列処理

ドキュメントをインデックスに送信すると、各インデックスはシャードで構成されます。シャードはクラスター内のワーカーです。これらはインデックスのサブ要素であり、それぞれが個別のドキュメントセットを含んでいます。OpenSearchはシャードをクラスター内のデータノードにマッピングし、これによりデータノードが処理を行います。
リクエスト処理

リクエスト処理では、リクエストはインデックスを参照し、いずれかのノードに到達します。そのノードはコーディネーターとして機能します。OpenSearch内では、特定のノードがコーディネーターとしてのみ機能するように指定することも、データノードがリクエストのコーディネーターとして機能することもできます。
コーディネーターの役割は、リクエストを読み取って解析し、各シャードへのリクエストに分割し、配布し、結果を受け取って集計し、再び送信することです。
検索クエリの場合、コーディネーターはこのインデックスには7つのノードにシャードがあることを認識します。7つの内部クエリを作成し、それらのシャードを持つノードにクエリを送信します。各シャードはシャードレベルの応答を返し、コーディネーターはすべてのシャードレベルの応答を集約してクエリ応答として返送します。
リクエスト処理の詳細

この層の下には、各ノードに多くの異なるキューがあり、各キューはそのノードが実行する種類の作業に対応しています。書き込みキュー、検索キュー、セグメントマージキューなど、数多くのキューがあります。
リクエストが来ると、キューに入れられ、データを持つノード、つまりそのデータノード上のシャードに送信されます。サブ要求もキューに入れられ、その後キューから取り出されてCPUとスレッドに送られます。それらが最終的にディスクとストレージRAM(ヒープまたはオフヒープ)にアクセスして要求を処理します。
インデックスの構造

これがリクエスト処理の流れです。では、データが実際にどのように保存されるかについて話しましょう。ドキュメントが入ってきて、このドキュメントにはメタデータ属性があり、ベクトルも持っています。それはシャードに送られます。
シャードはメタデータを取り込み、Luceneインデックスにインデックス化します。ベクトルデータも取り込み、やはりLuceneインデックスにインデックス化します。
ポスティングリストは、特定のフィールドが持つことができる値を取得し、それらの値を含むすべてのドキュメントのリストを作成します。ソースドキュメントは、無効にしない限り保存されます。Doc valuesと呼ばれるものもあり、これはドキュメントからそのドキュメント内の値への順方向マッピングです。これらは一部のタスクに使用されます。
Luceneファイルは全体で30〜40個存在します。ベクトル側では、ソースが保存され、ベクトルはDoc valuesにも保存されます。
OpenSearchの詳細アーキテクチャ

詳細には踏み込みませんが、データノード内の構造を見てみます。フィールドレベル、クエリレベル、リクエストレベルでキャッシュがあり、ベクトルキャッシュも別にあります。各シャードにはインデックスとベクトルネイティブライブラリがあり、メタデータとベクトルデータが分離して配置されています。
1億2500万の製品に向けたセマンティック検索を考える

これまでは背景として、構造とその仕組みを理解するための説明でした。ここから話す中心的なテーマは、1億2500万の製品のワークロードを計画することです。それぞれの製品には約2Kのメタデータがあり、1536次元のベクトルによるセマンティック検索をサポートしたいと考えています。
メタデータのインデックス変換

ベクトルインデックス作成のさまざまなパスについて説明しましょう。メタデータはインデックスに変換されます。ポスティングリストやソースなど、さまざまな要素があります。大まかな推測として、ドキュメントあたりのインデックスサイズは、メタデータサイズに約10%のインフレーションを加えたものです。これには多くのパラメーターが影響します。OpenSearchが提供するさまざまな圧縮方法により、最新のOpenSearchではソースからインデックスへの変換で70〜80%という低い値も見られますが、必要なストレージ量を把握するには10%のインフレーションを控えめなガイドとして使用してください。
オーバーヘッドも考慮する必要があります。OpenSearchはストレージがいっぱいになり始めるとノードのサービスを低下させます。いくつかのウォーターマークがあり、空き容量が15%を下回るとシャードの割り当てを停止し、10%を下回るとシャードの移動を開始し、0%になるとリクエストの受け入れを停止します。
したがって、常に少なくとも15%のオーバーヘッドが必要で、25%のオーバーヘッドを推奨しています。インデックスサイズを計算する際は、この25%も追加します。ディスク上では、ドキュメント数×メタデータサイズ×1.35がメタデータ部分を表します。1億2500万のドキュメントと2Kのメタデータでは、約345ギガバイトになります。
ベクトルのインデックス変換

ベクトルについては、次元数と次元あたりのバイト数を考慮します。実際には2倍必要です。なぜなら、ソースとDoc valuesの両方に保存するからです。
計算式は、ドキュメント数×ドキュメントあたりのサイズ×1.25(オーバーヘッド分)となります。1億2500万ドキュメント、1536次元、完全精度のベクトルでExact kNNの場合、約3テラバイトになります。ストレージコストの大部分をベクトルが占めることがわかります。
*最後に2を掛けている部分は、発表の意図に反して1ドキュメントに2つのベクトルを持つ場合を想定してスライドを書いてしまっていたので、今回の発表では無視して欲しい、との補足が発表内でありました
近似検索アルゴリズムとリソース消費

ここまでの議論は、ベクトルインデックスに対してブルートフォースマッチングを行うExact kNNを使用することを前提としていました。しかしこれはスケールしません。
ただし、ベクトルを高度にフィルタリングできる場合、Exact kNNは優れています。数千、おそらく数万程度なら実行可能です。レイテンシはドキュメント数、つまりベクトル数に比例します。
近似アルゴリズムによって、レイテンシを実際に削減できます。精度は低下してマッチングはそれほど良くありませんが、はるかに低いコストで十分なマッチングが得られます。
HNSW

OpenSearchがサポートする方法の1つがHNSW(Hierarchical Navigable Small World)です。
HNSWのアイデアは、インデックス作成時に近接点に対するグラフのセットを作成し、さまざまな粒度を持たせることです。粗いレベルでグラフを構築し、そのグラフをたどって近づき、より細かい粒度に落とし込んでまたグラフをたどって近づきます。できる限り近づくまでたどり、最終的に最も低い層で最も近い点を選択します。重要なパラメーターは、ストレージと効率の観点からのエッジ数です。これはパラメーター化されており、デフォルトはノードあたり16エッジです。グラフの構築などはすべて自動です。
これはインデックス作成時に行われます。すでに話したソースとDoc values(3テラバイト)に加えて、グラフを作成して保存する必要があります。これらのグラフはRAMに載せる必要があります。必要なメモリの式は、1.1 ×(4×次元数+8×エッジ数)×ベクトル数です。
次元あたり4バイト、グラフのノードあたり2つのエッジがあるので8バイト×エッジ数×ベクトル数で、ベクトルデータセットの総ストレージ容量が得られます。
数値を当てはめると、1.1×(4×1536次元+8バイト×16エッジ)×1億2500万ベクトルで、862GBが必要なRAMの量になります。
ストレージには25%のオーバーヘッドを追加するので、RAMの1.25倍をかけて、さらに1.08テラバイトのストレージが必要になります。
IVF

2番目の近似手法はIVF(Inverted File)です。IVFのアイデアは、K-meansクラスタリングを使用して関連点の重心を見つけることです。それらの重心を設定可能な数のバケットに配置し、検索を行う際に近い重心を見つけ、そのバケット内で検索します。主要なパラメーターは、バケット数であるnlistです。近い重心を見つけてその周辺だけを検索することで、検索空間を削減します。これらの重心は、そのクラスター内の点の代表的なものです。
IVFを使用するにはトレーニングが必要です。データの約10%を取得して重心を把握しますが、これはAPI呼び出しで実行できます。
RAMの計算式は、1.1 ×( (4×次元数×ベクトル数)+(4×nlist×次元数) )です。
数値を当てはめると、4×バケット数×次元数で844ギガバイトが必要なRAMの量になります。
ストレージは1.25×844で1.06テラバイトです。
レプリカのための倍増

これまでの計算はプライマリシャードだけを念頭に置いていました。しかし、通常少なくとも1つのレプリカシャードを使用して回復性を向上させる必要があります。そのため、レプリカのためにすべてを2倍にする必要があるのです。
ここまでのまとめ

ここまでの計算結果をまとめます。1億2500万のベクトル、1536次元、それぞれ2Kのメタデータという条件で考えてきました。
Exact kNN 、3.52テラバイトの2倍で約7テラバイトのストレージが必要になります。
HNSWを使用する場合は、345GBのメタデータ、3.07TBのベクトルデータ、862GBのグラフがあります。レプリカを考慮して2倍にすると、8.5テラバイトのストレージが必要で、グラフを保持するために862GBのRAMも必要です。
IVFを使用する場合は、詳細は省きますが、8.2テラバイトのストレージと844GBのRAMが必要です。
1億2500万のベクトルと1536次元という数字は確かに大きく、必要なリソースも膨大に感じるかもしれません。
リソースの最適化

もっと良い方法はないだろうかと思うかもしれません。はい、あります。それについて話しましょう。
Derived Source

まず、Derived Sourceについて話したいと思います。Derived Sourceは3.0でリリースされた機能です。インデックスを作成するときに有効にでき、knn.derived_source.enabled: trueと設定します。OpenSearchは、ソースフィールドまたはDoc valuesにデータを保存する代わりに、.vecという別のファイルを作成します。このファイルには、元の精度のベクトルがすべて含まれています。
vecファイルからソースとDoc valuesを再構築できます。多くの書き込みがあっても、これらを別々に保存するのと同じくらい高性能です。そして、ストレージを大幅に削減する手段を提供します。2つのコピーの代わりに、元の精度のベクトルデータのコピーが1つだけになるからです。ディスク上には.vecファイルとANNデータ(グラフまたはバケット)があり、RAMにはANNデータがあります。
Exact kNNの場合、約3.74テラバイトに減少します。HNSWの場合、約5.47テラバイトに減少し、862ギガバイトのRAMが必要です。IVFの場合、5.44テラバイトと844ギガバイトのRAMが必要です。Derived Sourceによって、元のデプロイメントサイズの半分強まで削減できています。
外部ビット削減

次のアイデアは、ストレージの多くが浮動小数点数の高いビット数によって占められているという点に着目することです。これを削減できないでしょうか。いくつかの方法があります。
最初の方法は、しきい値処理のようなビット削減技術を適用して、ベクトルデータをより小さなビット整数に変換することができます。
バイナリベクトルでは、次元あたり1ビットしか使わないため、ベクトル自体のサイズは125,000,000×1536÷8で24GBになります。
HNSWグラフの計算も、ベクトルのビット数削減に合わせて変わります。元の式の「4×次元数」の部分が「次元数÷8」になります。これは、グラフでもベクトル表現に同じビット削減を適用するためです。計算すると、1.1×(1536÷8 + 8×16)×125,000,000で44GBになります。
結果として、メタデータ345GB、ベクトル24GB、グラフ44GB(RAM)となり、レプリカを含めた総ディスクは826GB、必要RAMは44GBとなります。
削減幅がもう少し緩やかな8ビット整数の場合は、次元あたり1バイトを使用するため、ディスク容量1.5TB、RAM208GBになります。
どちらの場合でも、大幅な改善です。バイナリベクトルは精度を少し犠牲にしますが、厳密な検索と比較して90%台の精度を維持できます。
FAISSスカラー量子化

他の代表的な量子化方法として、FAISS(Facebook AI Similarity Search)エンジン用のFP16も挙げられます。これは次元あたり浮動小数点で2バイトに削減されます。
この方法を使用すると、ベクトルは125,000,000×1536×2に、さらに125,000,000×1536×4(.vecファイル用)を加えて750GBになります。グラフは次元あたり2バイトで計算し、1.1×(1536×2 + 8×16)×125,000,000で440GBになります。
最終的にメタデータ345GB、ベクトル750GB、グラフ440GBで、ディスク3TB、RAM440GBが必要になります。
Disk-based vector search

Disk-based vector searchについて話しましょう。Disk-based vector searchでは、元の32ビット浮動小数点数のベクトルを取得し、Product Quantization、Byte-vector Quantization、Binary Quantizationなどの異なる圧縮技術を適用して、HNSWグラフを構築するための圧縮ベクトルを作成します。
クエリを実行すると、まず圧縮ベクトルに対してクエリを実行し、オーバーサンプリングしてから、ディスクから取得した完全精度のベクトルに基づいて再スコアリングします。
この方法により、ディスク上では精度を大幅に維持しながら、グラフ内のベクトルのビット数を削減することでRAMの必要量を削減できます。
前提として、これまでのすべての計算にDerived Sourceを含めています。

Disk-based vector searchは、次元あたり1ビット(32倍圧縮)から完全精度(1倍)まで、圧縮レベルを設定できます。ここでは32倍圧縮を見ています。作成するグラフはバイナリベクトルを使用しますが、ディスク上には完全精度のベクトルが保存されています。完全精度のベクトルは.vecファイルに保存されています。
グラフは860GBから44GBに削減されました。これにより、ディスク1.6TB、RAM44GBという構成になります。圧縮レベルは1倍、2倍、4倍(Luceneのみ)、8倍、16倍、32倍から選択可能です。
Product Quantization(Derived Source含む)

これまでの近似手法に加えて、ビット数削減とは異なるアプローチもあります。しきい値処理や切り捨てによってビット数を削減する代わりに、サブベクトルの重心を見つける戦略です。これらの重心を使用して最近傍を見つけます。
具体的には、1536次元のベクトルをm個のサブベクトル(例えば8個)に分割し、K-meansクラスタリングを使用してサブベクトルごとに256個の重心を取得します。それらをコード化してテーブルに1バイトで保存し、検索を実行します。検索時は重心とサブベクトルを見つけ、コード化されたサブベクトルとして検索します。
この方法はビット数を大幅に削減してレイテンシを短縮できる高い能力がありますが、非常に圧縮されたレベルでは精度が大きく失われます。1億2500万のベクトルの場合、計算式はm×コードサイズ/8となり、769GBのベクトルストレージと17GBのグラフストレージになります。
レプリカを含めると1.6TB、RAMは17GBと非常に小さく、高速ですが、精度の損失が大きいです。
手法の比較まとめ

ベクトルの量子化やProduct Quantizationなど、さまざまな手法について、異なるデプロイメント形状を得るために多くのことを話してきました。
完全精度の厳密なマッチングは100%正確な結果をもたらしますが、レイテンシは悪化します。1億2500万のベクトルでは、確実に1秒以上のレイテンシが発生します。ブルートフォースアルゴリズムは非常に遅くなります。完全精度のベクトルと厳密な検索にDerived Sourceを使用すると、ストレージが削減され、精度は同じままでレイテンシも同じです。
HNSWを使用し、完全精度のベクトルとDerived Sourceを組み合わせた場合、ストレージは8.5TB、Derived Source使用時は5.47TB、RAMは862GBになります。ほぼ完璧なマッチングが得られ、おそらく99%の精度で、レイテンシは50ミリ秒程度に低下します。
表を見ていただければわかりますが、コスト、レイテンシ、再現率の間のバランスに注目すべき点があると思います。特にディスク検索では、削減されたビットベクトルに対する最初のクエリで最大200ミリ秒かかり、その後ディスクにアクセスして完全精度のベクトルを取得し、再スコアリングするのに時間がかかります。レイテンシは長くなりますが、非常に優れたRAM特性とストレージ特性が得られます。
Product Quantizationは70%程度の精度では許容できないものです。Product Quantizationでできることはたくさんありますが、精度を維持するために非常に注意する必要があります。しかし、最も小さいフットプリントを実現します。
コスト、レイテンシ、リコールのトレードオフ

ベクトルについて考えるとき、コスト、レイテンシ、リコールの間の三角関係を考える必要があります。これは、話してきたことすべてをグラフィックで示したものです。右上隅にExact KNNがあります。これは最大のコストですが、最も正確であり、同時に最も高いレイテンシを持ちます。
それに対してdisk based searchは、妥当なレイテンシと妥当な再現率を持ち、コストははるかに少なくなります。Memory-optimized、Scalar Quantization、Sparse Encodings、Binary Quantization、Product Quantizationなど、精度とレイテンシ特性に多少のばらつきがあり、コストも一般的に低い手法があります。
ディスクとメモリ以外の論点

では、元の問題に戻って、JavaヒープとCPUに関して残りのリソースについて少し話しましょう。
シャード設計

シャード自体が作業を行うものであることは先ほど説明しました。最初に考えることは、どのようにシャード分割するかです。32倍圧縮のディスクモードを使用するとしましょう。プライマリシャードのストレージは812GBです。
ANNワークロードにはより大きなシャードが推奨されます。なぜなら、検索空間を細かく分割して、小さな近傍を持つため、クエリを実行するときにより多くのデータをフィルタできるからです。
通常のテキスト検索ワークロードでは10〜30GBを推奨しますが、ANNワークロードの場合は50GB以上、場合によっては75GBまでシャードあたりまで推奨します。
50GBと仮定して、812を50で割ると約17シャードになり、18に切り上げます。シャードとノードの比率を計算するときは、常に3の倍数で考えるのが良いでしょう。
AWSでは3つの異なるアベイラビリティゾーンにデプロイするため、3つの方法に分割できることは良いことです。AWS以外、オンプレミスでも、分離と回復性のために複数のゾーンを持つべきです。レプリカを含めると、合計36シャードになります。
CPU要件

32倍圧縮のディスクモードで、これらの36シャードは作業を行うためにCPUにマッピングされます。一般的な推奨事項は、シャードあたり1.5CPUを使用することです。
なぜこの比率なのでしょうか。もしシャードあたり1CPUを使用し、そのシャードが100%占有されている場合、CPUが残っていません。クラスター内では、セグメントのマージや通信など、他にも多くのことが行われています。そのため、CPUを100%占有することはできません。良い目標は3分の2、つまり67%です。検索ワークロードでは、シャードあたり1.5CPUになります。このクラスターでは54CPUを目標とします。
RAM要件

RAMに関しては44GB必要です。75対25のオフヒープとヒープの比率を推奨しています。また、1ノードあたりのヒープの最大値は32Gを推奨しています。
ただし、これはあくまで例です。実際の検索ワークロードで必要なヒープの量は、実行しているクエリや、語彙検索における一時的な構造によって消費されるヒープの量に大きく依存します。メタデータ属性によるフィルタリングを多用する場合、より大きなヒープが必要になります。
75対25の比率で計算すると、このクラスターでは128GBのRAMが必要です。
まとめとインスタンス選択

データノードを選びます。私はAWSソリューションアーキテクトなので、AWSノードが最もよくわかります。i4i.2xlargeを推奨します。これは8vCPU、64GBのRAM、1.875TBのSSDを搭載しており、Intelベースのインスタンスであるため、OpenSearchは自動的にIntelベースのベクトルアクセラレーションを使用します。
54CPUの必要性に基づいて9つのインスタンスが必要であり、3つのアベイラビリティゾーンに均等に配置できるようにします。オンデマンドで月額約7,000ドルになりますが、おそらく少々オーバースケールでしょう。