Azure AI Search のパフォーマンス向上に関するヒント

この記事には、クエリとインデックス作成のパフォーマンスを向上させるために推奨されることの多いヒントとベスト プラクティスがまとめられています。 検索のパフォーマンスに最も影響しやすい要因を把握することは、非効率性を回避し、検索サービスを最大限に活用するのに役立ちます。 主な要因は次のとおりです。

  • インデックスの構成 (スキーマとサイズ)
  • クエリの設計
  • サービスの容量 (レベル、レプリカとパーティションの数)

Note

大量のインデックス作成に関する戦略をお探しの場合は、 Azure AI Search で大規模なデータ セットのインデックスを作成するを参照してください。

インデックスのサイズとスキーマ

クエリは、インデックスが小さいほど実行速度が上がります。 これは、スキャンするフィールド数が少なくなることも一因ですが、今後のクエリに備えてシステムがコンテンツをキャッシュする方法にも起因しています。 最初のクエリの後、一部のコンテンツは、検索がより効率的に行われるメモリの中に残ります。 インデックスのサイズは時間と共に大きくなる傾向があるため、ベスト プラクティスの 1 つは、インデックスの構成 (スキーマとドキュメントの両方) を定期的に見直して、コンテンツを削減する機会を探ることです。 ただし、インデックスが適正なサイズに設定されている場合は、レプリカを追加するかサービス レベルをアップグレードして、容量を増やすだけで調整できます。 「ヒント: Standard S2 レベルにアップグレードする」セクションでは、スケールアップとスケールアウトの決定について説明しています。

スキーマの複雑さがインデックス作成とクエリのパフォーマンスに悪影響を及ぼすこともあります。 フィールド属性が多すぎると、制限事項や処理要件が増えます。 複合型では、インデックス作成とクエリに時間がかかります。 次のいくつかのセクションでは、各条件について詳しく説明します。

ヒント: フィールド属性の選択に慎重になる

検索インデックスの作成時に管理者と開発者が犯す一般的な間違いは、必要なプロパティだけを選択するのではなく、フィールドに関して使用可能なすべてのプロパティを選択することです。 たとえば、フィールドをフルテキスト検索可能にする必要がない場合は、検索可能属性の設定時にそのフィールドをスキップします。

選択的属性

フィルター、ファセット、並べ替えをサポートすると、ストレージ要件が 4 倍になる可能性があります。 suggester を追加すると、ストレージ要件がさらに増えます。 ストレージへの属性の影響の具体例については、「属性とインデックスのサイズ」をご覧ください。

属性が多すぎる場合の悪影響をまとめると、次のようになります。

  • フィールド内のコンテンツを処理した後、検索の転置インデックスにそれを格納する (検索可能なコンテンツが含まれているフィールドにのみ "検索可能" 属性を設定する) のに余分な作業が必要となるためインデックス作成のパフォーマンスが低下します。

  • 各クエリの対象にしなければならない領域が増大します。 検索可能とマークされたすべてのフィールドがフルテキスト検索でスキャンされます。

  • 追加のストレージによって運用コストが増加します。 フィルター処理と並べ替えには、元の (分析されていない) 文字列を格納するための追加の領域が必要です。 それが不要なフィールドでは、フィルター可能や並べ替え可能の設定を行わないようにしてください。

  • 多くの場合、属性が多すぎると、フィールドの機能が制限されます。 たとえば、フィールドがファセット可能、フィルター可能、および検索可能の場合、そのフィールド内には 16 KB のテキストしか格納できませんが、検索可能のフィールドでは最大 16 MB のテキストを保持できます。

Note

不要な属性のみを避ける必要があります。 フィルターやファセットは、検索操作に不可欠な場合が多く、フィルターが使用されている場合は、結果を順序付けするために並べ替えが必要になることがよくあります (フィルター自体は順序付けされていないセットで返されます)。

ヒント: 複合型に代わる方法を検討する

複合データ型は、JSON ドキュメント内で見られる親子要素など、複雑な入れ子構造がデータに含まれている場合に便利です。 複合型の欠点は、非複合データ型と比較して、追加のストレージ要件と、コンテンツのインデックス作成に必要な追加リソースが発生することです。

場合によっては、複雑なデータ構造をより単純なフィールド型 (コレクションなど) にマップすることによって、こうしたトレードオフを回避できます。 あるいは、フィールドの階層を個々のルート レベルのフィールドにフラット化することを選択できます。

フラット化されたフィールド構造

クエリの設計

クエリの構成と複雑さは、パフォーマンスの最も重要な要因の 1 つであるため、クエリの最適化によってパフォーマンスが大幅に向上する可能性があります。 クエリをデザインするときは、次の点を考慮してください。

  • 検索可能なフィールドの数。 検索可能なフィールドが 1 つ増えるごとに検索サービスの処理負荷が増えます。 "searchFields" パラメーターを使用すると、クエリ時に検索されるフィールドを制限できます。 パフォーマンスを向上させるために重要と思われるフィールドのみを指定することをお勧めします。

  • 返されるデータの量。 大量のコンテンツを取得すると、クエリの実行速度が下がる可能性があります。 クエリを構築する場合は、結果ページをレンダリングするために必要なフィールドだけを返し、ユーザーが一致を選択した後で、LOOKUP API を使用して残りのフィールドを取得します。

  • 部分的な用語検索の使用部分的な用語検索 (プレフィックス検索、あいまい検索、正規表現検索など) では、結果を生成するためにインデックスの完全スキャンを必要とするため、一般的なキーワード検索よりも計算負荷が高くなります。

  • ファセットの数。 クエリにファセットを追加するには、クエリごとの集計が必要です。 ファセットに、より高い "カウント" を要求する場合も、サービスによって追加の作業が必要になります。 一般に、アプリに表示しようとしているファセットだけを追加し、必要ない限り、ファセットにより高いカウントを要求しないようにします。

  • 高いスキップ値。 $skip パラメーターを大きな値 (千単位など) に設定すると、エンジンは要求ごとに大量のドキュメントを取得してランク付けするため、検索の待機時間が長くなります。 大量のドキュメントを取得する場合、パフォーマンス上の理由から、高い $skip 値を避け、フィルター処理などの他の手法を代わりに使用することが最も適切です。

  • 高カーディナリティ フィールドを制限する。 "高カーディナリティ フィールド" とは、多数の一意の値を含むファセット可能またはフィルター可能フィールドのことです。そのため、結果を計算するときに膨大な量のリソースを消費します。 たとえば、製品 ID または説明フィールドをファセット可能かつフィルター可能として設定すると、ドキュメント間でほとんどの値が一意であるため、高カーディナリティと見なされます。

ヒント: フィルター条件をオーバーロードする代わりに検索関数を使用する

クエリでますます複雑なフィルター条件が使用されるのに伴って、検索クエリのパフォーマンスが低下します。 フィルターを使用してユーザー ID に基づいて結果をトリミングする次の例について考えてみましょう。

$filter= userid eq 123 or userid eq 234 or userid eq 345 or userid eq 456 or userid eq 567

この場合、フィルター式を使用して、各ドキュメント内の 1 つのフィールドが、ユーザー ID の考えられる多くの値のいずれかと等しいかどうかを確認します。 このパターンは、セキュリティによるトリミング (1 つ以上のプリンシパル ID を含むフィールドを、クエリを発行するユーザーを表すプリンシパル ID のリストと照合する機能) を実装しているアプリケーション内で最もよく見られます。

多数の値を含むフィルターを効率的に実行する方法は、次の例に示すように、search.in 関数を使用することです。

search.in(userid, '123,234,345,456,567', ',')

ヒント: 個々の低速クエリに対応するためにパーティションを追加する

通常、クエリのパフォーマンスが低下している場合は、レプリカを頻繁に追加すると問題が解決することがよくあります。 しかし、この問題が、完了までに時間がかかりすぎる 1 つのクエリである場合はどうでしょうか。 このシナリオでは、レプリカを追加しても問題は解決しませんが、パーティションを追加すると解決する可能性があります。 パーティションによって、追加のコンピューティング リソース間でデータが分割されます。 たとえば、パーティションが 2 つの場合はデータが半分に分割され、パーティションが 3 つの場合は 3 分の 1 に分割されます。

パーティションの追加によるプラスの副作用の 1 つは、並列コンピューティングのために低速クエリが高速で実行される場合があることです。 多数のドキュメントと一致するクエリや、多数のドキュメントの数をカウントするファセットなど、選択度の低いクエリの並列処理に注目しました。 ドキュメントの関連性を評価したり、ドキュメントの数をカウントしたりするために、膨大な量の計算が必要となるため、パーティションを追加することでクエリをより速く完了できます。

パーティションを追加する場合は、Azure portalPowerShellAzure CLI、または管理 SDK を使用します。

サービスの容量

サービスに過度の負荷がかかると、クエリに時間がかかりすぎたり、要求に応答できなくなったりします。 その場合は、サービスをアップグレードするか容量を追加することで問題に対処できます。

検索サービスのレベルやレプリカまたはパーティションの数も、パフォーマンスに大きな影響を与えます。 しだいにレベルを上げていくと CPU が高速化され、メモリ容量が増えるので、その両方によりパフォーマンスが向上します。

ヒント: 新しい高容量検索サービスを作成する

2024 年 4 月 3 日より後に[サポートされているリージョンで] (サポートされているリージョン) 作成された Basic および Standard サービスでは、古いサービスよりもパーティションあたりのストレージが増加しています。 より高いレベルおよびより高い課金対象レートにアップグレードする前に、レベルのサービスの制限に関する記事を再確認して、新しいサービスの同じレベルで必要なストレージが提供されるかどうかを確認してください。

ヒント: Standard S2 レベルにアップグレードする

多くの場合、顧客は Standard S1 検索レベルから開始します。 S1 サービスの一般的なパターンでは、インデックスが時間と共に増加し、それに伴ってより多くのパーティションが必要になります。 パーティションが増えると応答時間が長くなるので、クエリの負荷に対処するためにより多くのレプリカが追加されます。 ご想像のように、S1 サービスの実行にかかるコストは、初期構成を超えたレベルに達しています。

この時点で、現在のサービスのパーティションまたはレプリカの数を段階的に増やすのではなく、上位レベルに移行することが有益かどうかを判断することが重要です。

容量のレベルを上げたサービスの例として、次のトポロジを考えてみましょう。

  • Standard S1 レベル
  • インデックス サイズ: 190 GB
  • パーティション数: 8 (S1 の場合、パーティション サイズはパーティションあたり 25 GB)
  • レプリカ数: 2
  • 検索単位の合計: 16 (8 つのパーティション x 2 つのレプリカ)
  • 架空の小売価格: 約 4,000 米国ドル/月 (250 米国ドル x 16 検索単位を想定)

サービス管理者は依然として待機時間が長いと感じており、レプリカをもう 1 つ追加することを検討しているとします。 これにより、レプリカ数が 2 から 3 に変更され、その結果、検索単位数が 24 に変更されて、価格が 6,000 米ドル/月となります。

一方、管理者が Standard S2 レベルへの移行を選択した場合、トポロジは次のようになります。

  • Standard S2 レベル
  • インデックス サイズ: 190 GB
  • パーティション数: 2 (S2 の場合、パーティション サイズはパーティションあたり 100 GB)
  • レプリカ数: 2
  • 検索単位の合計: 4 (2 つのパーティション x 2 つのレプリカ)
  • 架空の小売価格: 約 4,000 米国ドル/月 (1,000 米国ドル x 4 検索単位)

この架空のシナリオで示すように、下位レベルの構成を使用すると、最初の段階で上位レベルを選択した場合と同様のコストになります。 ただし、上位レベルには Premium Storage が付属しており、これにより、インデックス作成の速度が向上します。 また、上位レベルでは、コンピューティング能力が大幅に上がるだけでなく、追加のメモリもあります。 同じコストで、同じインデックスをサポートする、より強力なインフラストラクチャを構築できます。

メモリを追加することの重要な利点は、より多くのインデックスをキャッシュできることです。これにより、検索の待ち時間が短縮され、1 秒あたりのクエリ数が増加します。 この追加の機能があれば、管理者はレプリカ数を増やす必要すらない場合もあり、S1 サービスを使い続けるよりも費用が少なくなる可能性があります。

ヒント: 正規表現のクエリに代わる方法を検討する

たとえば、正規表現のクエリや正規表現は特にコストがかかります。 高度な検索には非常に便利ですが、正規表現が複雑な場合や大量のデータを検索する場合は特に、実行に多くの処理能力が必要になる場合があります。 これらの要因に寄って、検索待ち時間が長くなる可能性があります。 軽減策として、正規表現を簡略化するか、複雑なクエリをより小さく管理しやすいクエリに分割してみてください。

次のステップ

サービスのパフォーマンスに関連する他の記事を確認します。