Loading
Salesforce から送信されるメールは、承認済ドメインからのみとなります続きを読む

SOQL クエリを選択的にする

公開日: Apr 2, 2026
説明
非選択的クエリは、(Apex トリガ、または、バッチ Apex クラスのような) 異なるプログラミングの要素を失敗させる可能性があります。大きなオブジェクトをクエリするとき、特別な設計上の考慮をする必要があります。
解決策
SOQL クエリの複雑さは、項目がインデックスの作成に適しているかどうかに大きな影響を与えています。弊社は、標準およびカスタムインデックスがどのように異なるのか、どのように採用されているのかを完全に理解するために、次の資料を閲覧することを強く推奨します。

考慮事項: Salesforce SOQL クエリオプティマイザが高いレベルでどのように動作するかを説明する努力が行われてきましたが、その動作は追加のパフォーマンス強化に対応するために、予告なく変更することがあります。開発者は、開発者コンソール内でクエリプランビュー(Summer '14 から利用可能)を使用することが推奨されています。

SOQL のパフォーマンスは、選択的フィルタの存在に依存します。SOQL クエリが少なくとも一つの選択的フィルタを含んでいる場合、そのクエリは選択的であると言われます。SOQL クエリが選択的フィルタを含んでいない場合、そのクエリは非選択的であると言われ、フルテーブルスキャンを必要とします。

クエリオプティマイザの観点から、フィルタはシンプルであるか、複合的であることができます。シンプルフィルタは "AND" 演算子を使用する条件式で、それぞれの項目の式(<field> <operator> <value>)となります。対照的に "OR" 演算子を使用して、2 つ以上の項目の式を結合した結果が複合フィルタです。
  • fieldExpression1 AND fieldExpression2 - 2 つのシンプルフィルタを示しています
  • fieldExpression1 OR fieldExpression2 - 複合フィルタです
  • fieldExpression1 AND (fieldExpression2 OR fieldExpression3) - 2 つのフィルタを示しています(一つはシンプルで、もう一つが複合です)


シンプルフィルタが選択的であることを確認します
  • インデックスを持っているかを判断します
    • フィルタが標準項目にあるとき、それがプライマリキー(Id、Name、OwnerId)、外部キー(CreatedById、LastModifiedById、ルックアップ、主従関係)、および、監査項目(CreatedDate、SystemModstamp)である場合に、インデックスを持ちます。
    • カスタム項目は、一意、あるいは外部 ID としてマークされた場合にインデックスを持ちます。
  • フィルタがインデックスを持たない場合、最適化のために考慮されません。
  • フィルタがインデックスを持っている場合、何件のレコードが返されるかを決定します。
 
  • 標準インデックスでは、しきい値は最初の 100 万ターゲットレコードの 30 パーセント、最初の 100 万レコードの後はすべてのレコードの 15 パーセントです。さらに、標準インデックスの選択的しきい値は、560 万以上の合計レコードを持っていた場合にのみに達する可能性がある 100 万ターゲットレコードで限界に達します。
  • カスタムインデックスでは、選択的しきい値は最初の 100 万ターゲットレコードの 10 パーセント、最初の 100 万レコードの後はすべてのレコードの 5 パーセントです。さらに、カスタムインデックスの選択的しきい値は、560 万以上の合計レコードを持っていた場合にのみに達する可能性がある 333,333 ターゲットレコードで限界に達します。
 
  • フィルタがしきい値を超えた場合、最適化のために考慮されません。
  • フィルタがしきい値を超えていない場合、このフィルタは選択的です。そして、クエリオプティマイザは最適化のために、それを考慮します。

例:
1. SOQL クエリを取得し、count() 演算子で項目の一覧を置き換えます。

SELECT count() FROM Appointment__c WHERE CreatedDate = this_year AND Status__c = 'Available' 

2. テーブルのアクティブなレコードの数を確認します。

Select count() from Appointment__c
# of records: 239619
Threshold for standard indexes: 30% * 239619 = 71885
Threshold for custom indexes: 10% * 239619 = 23961

3. インデックスを持つ WHERE 句の唯一のフィルタは、CreatedDate です。そのため、この項目のフィルタを考慮するだけです。

Partial SOQL query: Select count() from Appointment__c where CreatedDate = this_year
# of records: 84567 > threshold for standard indexes
Is the used filter selective? NOT

4. Status__c のフィルタが選択的でるかどうかを確認しましょう。

Partial SOQL query: Select count() from Appointment__c where Status__c = 'Available'
# of records: 14397 < threshold for custom indexes

5. Status__c がカスタムインデックスである場合、"Status__c = 'Available'" は選択的フィルタでしょう。したがって、SOQL クエリは選択的でしょう。
 
項目にカスタムインデックスを付与するためには - 新規ケースを作成し、影響を受けた SOQL クエリ、テストに使用することができるユーザ ID、および、使用したバインド変数の値 を提供してください。

カスタムインデックスを不適切に使用すると、クエリの結果が遅くなることがあります。クエリの対象となるオブジェクトに必要な行のみを Force.com がスキャンするように、選択性のあるフィルタ条件を作成することが最善です。Force.com のクエリオプティマイザは、非選択的なフィルタ条件を含むクエリには、そのフィルタ条件が参照する項目にすでにインデックスがある場合でも、インデックスを使用しません。


カスタムインデックスのサポートへのお問い合わせに記載する内容のチェックリスト

次の情報は必ずお問い合わせに記載するようにしてください。これらの情報を提供する必要がある理由は以下の通りです。
  1. インデックス対象の項目 - どの項目を重視し、どの項目を残しておくべきかを確認します。
  2. 結合値を使用した SOQL クエリ - フィルタ条件の一部として項目を含める。Severity__c をフィルタリングするクエリが必要な場合、ログイン権限があれば、カスタム項目 Severity__c のサンプル値をすることができます。
    • Select Id, Case_Number__c from Case where Severity__c = 'Critical' - 正解です。ここで Critical は結合値です。
    • Select Id, Case_Number__c from case where Severity__c = :severityLevel - 間違っています。このクエリは実行できません。
  3. ログインアクセス - ログインアクセスがあれば、問題を再現して正しく理解することができます。
  4. エラーメッセージ/タイムスタンプ - エラーログ/タイムスタンプがあれば、インデックスの必要性を理解するのに役立ちます。
  5. エラーを再現するための手順 - お客様が行ったのと同じ手順を踏むことで、問題をより深く理解することができます。
  6. 追加フィルタの可能性を評価する - 機能に影響を与えずにクエリに追加フィルタを追加することで、インデックスを追加することなく問題を解決できる場合があります。インデックスを作成できない場合や、インデックスがマイナスになる場合は、結果として得られるレコードの数を減らすために、クエリに追加のフィルタを追加することをお勧めします。それができない場合は、フィルタを追加できない理由を教えていただければ、追加の可能性を検討します。
  7. 上記手順の 4 と 5 の情報がわからない場合は、適切な理由なしに項目にインデックスを作成するとパフォーマンスが低下する可能性があるため、なぜそれが必要なのかを説明してください。

一つ以上のシンプルフィルタが選択的である場合に、どのようなことが起きますか? クエリオプティマイザは、クエリの実行プランを動作させるための低コストなものを選択します。

複合的フィルタが選択的かどうかをどのように把握すればよいですか? オプティマイザは、シンプルフィルタのそれぞれが選択的であるかどうかを決定します。そして、合計で返されるレコードの数がしきい値を超えない場合については上述しました。これらの条件が合致している場合、フィルタは選択的であるでしょう。
ナレッジ記事番号

000385218

 
読み込み中
Salesforce Help | Article