投稿者:Tetsuo Ajima | 投稿日:2010年9月17日(金) 09:44

最初に確認すべきポイント

まず最初に確認すべきポイントは、SOQLクエリの検索条件です。
SOQLクエリの検索条件にインデックス化された項目が含まれているかどうかを確認してください。

[Select Field1__c, Field2__c, Field3__c From CustomObject__c Where Field1__c = :value]

上記の場合、データベースにて Field1__c のインデックスが作成されている必要があります。


インデックスの作成

データベース内部で項目のインデックスを作成させるには、項目の編集画面にて「外部 ID」チェックボックスをONにします。

※カスタム項目の編集画面
Photo

「外部ID」項目はUpsert処理のキーに利用する項目ですが、「外部ID」に指定された項目はデータベース内部でインデックスが作成されるので、パフォーマンスチューニングのためにこの設定をするという使い方が可能です。
「外部ID」項目は、1つのオブジェクトに対してデフォルトで3つまで指定できます。

ただし、インデックス化された項目を検索条件にした場合の絞り込みがデータ全体の1/10以下になるようなデータ分布でないと、インデックス作成の効果は無いことに注意してください。
(追記: データ全体の件数が100万件以上になる場合は1/20以下に絞り込めないとインデックスとしての効果がありません。)
また、Id項目やName項目、監査日付項目(例: LastModifiedDate)などはデフォルトでインデックス化されています。IdやNameを検索条件にした検索は高いパフォーマンスを期待できます。
(追記: 標準項目のインデックスは、データ全体の30%以下に絞り込めること、かつ絞り込んだ件数が33万3千件以下である必要があります。カスタム項目のインデックスは、絞り込んだ件数が100万件以下である必要があります。)


検索条件にインデックス化された項目が複数含まれる場合

検索条件にインデックス化された項目が複数含まれる場合は、Force.comプラットフォームのクエリオプティマイザが実行計画を立てる際に、効果が高いと判断された項目が優先して使用されます。


データ件数が多い場合

検索対象のオブジェクトに格納されているデータ全体の件数が多いと検索のパフォーマンスに影響します。
筆者の経験では、Apexトリガなら10万件、Visualforceコントローラやレポート・リストビューの実行であれば100万件を超えるような場合に、検索条件となる項目のインデックスが作成されているかどうかに注意すべきです。とは言え、利用が進むにつれてデータ量が増大することも考慮し、またより快適なレスポンスを得るためには検索条件となる項目を常にインデックス化することを推奨します。
Triggerでは10万件以上のデータから検索する時はインデックス化された項目が検索条件に含まれていないとエラーになる場合があります。TriggerではDMLが発行されてからコミットされるまでの間の処理を行うため、高い応答性能が求められるためです。


削除済みデータの考慮

Force.comアプリケーションのデータは次の3種類の状態があります。
1. Activeなデータ。通常の操作で参照・更新可能な状態
2. 削除され、ごみ箱に入っているデータ。ごみ箱から復元可能な状態
3. ごみ箱から削除され、内部的に物理削除されるのを待っている状態のデータ。画面上からは確認不可
上記の1.の状態のみでなく、2.および3.の状態で存在するデータの件数も検索のパフォーマンスに影響します。3.の状態のデータは一定間隔でバックグラウンドで物理削除されますが、大量のデータを削除した直後はクエリオプティマイザによるクエリ実行計画の最適化に反映されるまで1~2日程度かかる場合があります。
ちなみに、2.および3.の状態のデータは、SOQLクエリに isDeleted=TRUE および ALL ROWS を付加することによって取得・参照することができます。

[Select Field1__c, Field2__c, Field3__c From CustomObject__c Where isDeleted=TRUE ALL ROWS]


その他のチューニングの手段

Force.comプラットフォームにはDivisionという、データベースパーティションのような概念を持った機能があります。Divisionの方がパフォーマンス改善に対する効果は高いのですが、いろいろな制約があります。Divisionについてはまた別の機会に述べたいと思います。


レポートおよびリストビュー

本稿ではSOQLクエリの実行にフォーカスして述べていますが、レポートやリストビューの実行にもまったく同様のチューニングが適用可能です。レポートやリストビューの抽出条件に利用する項目がインデックス化されるようにすることで、レスポンスの改善を期待できます。


日々成長しています

ここに述べたようなチューニングを適切に行えば、数千万件のデータに対するクエリも実用上問題なく利用できます。弊社内で行ったテストでは、1億件以上のデータに対するクエリも実用的な応答性能が得られたという実績もあります。
Salesforceのデータセンターでは、24時間体制で常にサーバ負荷や応答性能の監視を行っています。インフラの増強も必要に応じて随時行っておりますので、ここで述べたようなパフォーマンスチューニングのノウハウも近い将来通用しなくなるかもしれません。サービスベンダーにより日々メンテナンスされ必要に応じた増強が行われるのもクラウドのメリットですね :-)