Salesforce Developers Japan Blog

Force.com SOQLベストプラクティス – WHERE句条件のNULL値や数式項目について

大量データを扱うSOQLのベストプラクティスとして、WHERE句条件にNULL値や数式項目を使用することは、Winter’13リリース まで推奨されませんでした。しかしながら、今後新規SOQLの実装をする際、またはWinter’13リリース以前に実装された既存のSOQLに対するパフォーマンス改善やインプリの見直しを計画されている場合には、以下のNULL値および数式項目を使用したWHERE句条件に関する新たなベストプラクティスが役立つかもしれません。

数式項目に対するカスタムインデックス

数式項目は他の項目を参照したり、値や関数と使ったりすることで動的に値を計算して表示できるカスタム項目です。

他のタイプの項目(テキストや数値)をSOQLのWHERE句に使用できるように、数式項目についても以下のようにSOQLのWHERE句に使用できます。

SELECT Id, Name FROM Contact WHERE FormulaField__c = '10';

ただし、数式項目はWHERE句に使用できるものの、使用を推奨するものではありません。

これは数式項目がインデックスを持たないため、WHERE句に指定された場合には条件に合致するデータを抽出するために大量のブロックを読み込む必要がある事に加え、数式項目はデータベース内に計算結果を保持しておらず、参照される度に動的に計算結果を生成しているため、大量のレコード数を対象にSOQLを発行した際にWHERE句に数式項目を使用していると非常に処理時間を要するためです。

これまで数式項目に対してインデックスが使用できないため、多くの回避策が検討されてきました。

例えば、Apex トリガやワークフローを使用し、数式項目の値を別のカスタム項目に格納してインデックス化し、代わりにWHERE句に使用する等が挙げられます。

しかし、これらの対応策は追加の設定作業を要し、開発上も効率的であるとは言えません。

これを改善するため Winter’13リリースからはカスタマーサポートに連絡することで、特定の数式項目に対してカスタムインデックスを付与できるようになりました。以下に引き続きインデックスを付与できない条件を記載します。

  • 他のオブジェクトに対してリレーションを持っている (例. 参照項目による別オブジェクトの参照)

  • 他のオブジェクトにリレーションを持つ数式項目を含む数式項目

  • 動的な日付関数を使用した数式項目 (例. TODAY() や NOW() 等)

また、以下の項目を含む場合にも、インデックスを付与できません。

  • 所有者(OwnerId)、自動採番項目、ディビジョン(Divisions)、監査項目(作成日(CreatedDate)、作成者(CreatedId))

  • 以下の項目はもともとインデックスを付与できないため、これらを含む数式もインデックスは付与できません。

    • 複数選択リスト

    • マルチ通貨が有効化されている組織における通貨項目

    • ロングテキスト項目、リッチテキスト項目

    • バイナリ項目 (Blob、File、暗号化項目)

  • 特別な機能を持つ標準項目

    • 商談(Opportunity)オブジェクトの取引先(AccountId)項目、数量(TotalOpportunityQuantity)項目、期待収益(ExpectedRevenue)項目、IsClosed項目, IsWon項目

    • ケース(Case)オブジェクトのクローズ日時(ClosedDate)項目、IsClosed項目

    • 商品(Product)オブジェクトの商品ファミリ(Product Family)項目、有効(IsActive)項目、isArchived 項目

    • ソリューション(Solution)オブジェクトの状況(Status)

    • リード(Lead)オブジェクトのリード状況(Status)項目

    • 活動(Activity)オブジェクト(Task/Event)の件名(Subject)項目、状況(Status)項目、優先度(Priority)項目

これらの項目は関連するオブジェクトが更新された際に影響を受けて値が変化したり、時間経過と共に値が変わってしまうため、数式項目に含まれていると、インデックスを付与できません。

※数式項目にインデックスを作成した場合でも常に使用されるわけではなく、インデックスが有効に動作する条件に合致して、初めてパフォーマンスの改善に寄与します。インデックスの使用条件詳細については「Force.com Apex コード開発者ガイド」の「非常に大きい SOQL クエリの処理」をご参考下さい。

上記の条件に当てはまらない数式項目にカスタムインデックスを付与する場合には、カスタマーサポートまで連絡して下さい。

NULL値の項目に対するカスタムインデックス

以下のように、SOQLのWHERE句の条件にNULL値を指定するケースが多々あります。

SELECT Id, Name FROM Contact WHERE CustomField__c = null;

一 見シンプルなWHERE句に見えますが、対象オブジェクト上のレコードが大量にある場合にはパフォーマンスを考慮する必要があります。Force.com 上の項目にインデックスが付与されている場合でも、NULL値を条件とした場合にはインデックスは有効に動作しません。そのため上記の様なSOQLの場合、対象レコードを抽出するためにすべてのレコードを対象に、大量のブロックを読み込む必要があり、パフォーマンスが最適化できず、処理に時間を要します。

これを改善するため、Winter’13からはカスタマーサポートに連絡することで、カスタムインデックスを有効化する際に、NULL値も含めることができるようになりました。もし既に対象項目にカスタムインデックスがある場合には、再度カスタマーサポートに連絡し、明示的にNULL値に対するインデックスを再作成する必要があります。

※このオプションは選択リスト項目、外部ID項目、参照項目/主従関係項目には適用されません。

もしNULL値を条件とする外部ID項目に対してパフォーマンスを改善する必要がある場合には、カスタマーサポートに連絡し、複合(2項目)カスタムインデックスの作成を検討する必要があります。

NULL値に対するカスタムインデックスについても、作成しても常に有効に使用されるというものではありません。インデックスが有効に動作する条件に合致して、初めてパフォーマンスの改善に寄与します。NULL値を条件とするSOQLを使用する場合には「Best Practices for Deployments with Large Data Volumes」(英語)についてもご参考下さい。

まとめ

SOQLを作成する際には、数式項目に対するインデックス、およびNULL値に対するインデックスについて検討してみてください。もしこれらの新たなオプションが有効に動作する条件に合致していれば、SOQLのパフォーマンスの改善が見込めるため、是非お試し下さい。

上記の記載のとおり、どちらのオプションも有効化するためにはカスタマーサポートへ連絡する必要があります。また、詳細については「Best Practices for Deployments with Large Data Volumes」(英語)も大変参考になります。是非、ご確認ください。

関連ドキュメント

原文

Force.com SOQL Best Practices: Nulls and Formula Fields

コメント

Force.com SOQLベストプラクティス – WHERE句条件のNULL値や数式項目について