Salesforce Big Objects: 大規模データ管理のための包括的ガイド

背景と適用シナリオ

Salesforceは強力なCRMプラットフォームですが、データ量の増大は常にアーキテクトにとっての課題です。標準オブジェクトやカスタムオブジェクトに数千万、数億件のレコードを保存すると、ストレージコストの増加、パフォーマンスの低下、ガバナ制限への抵触など、さまざまな問題が発生します。特に、レポートやリストビューの読み込みが遅くなったり、SOQLクエリがタイムアウトしたりすることは、ユーザーエクスペリエンスを著しく損ないます。

このような大規模データの問題を解決するためにSalesforceが提供しているのが Big Objects (ビッグオブジェクト) です。Big Objectsは、Salesforce Platform上で数十億件のレコードを安定して格納し、非同期的にクエリを実行するために設計された特別なオブジェクトです。標準オブジェクトとは異なり、ビッグデータ技術(Apache HBaseを基盤としています)を活用しており、パフォーマンスを維持しながら膨大なデータを扱うことができます。

Big Objectsの主な適用シナリオは以下の通りです。

1. データアーカイブ

商談、ケース、活動履歴など、時間の経過と共に関心が薄れるものの、コンプライアンスや将来の分析のために保持する必要があるデータをアーカイブするのに最適です。例えば、完了から3年以上経過したケースレコードを標準のCaseオブジェクトからBig Objectに移動させることで、Caseオブジェクトのパフォーマンスを維持しつつ、履歴データを低コストで保持できます。

2. 顧客の360度ビュー

Webサイトのクリックストリーム、IoTデバイスからのセンサーデータ、購買履歴、モバイルアプリの操作ログなど、顧客に関連する大量のインタラクションデータを格納するのに利用できます。これらのデータをBig Objectに集約することで、顧客の行動パターンを詳細に把握し、よりパーソナライズされた体験を提供するためのインサイトを得ることが可能になります。

3. 高頻度の監査と追跡

システムの詳細な操作ログ、API連携のトランザクションログ、フィールドの変更履歴など、大量に生成されるログデータを保存するのに適しています。これにより、セキュリティ監査やシステムの利用状況分析に必要なデータを、Salesforceプラットフォーム内で一元管理できます。


原理説明

Big Objectsは、標準オブジェクトとは根本的に異なるアーキテクチャと特性を持っています。その核心となる概念を理解することが、効果的に活用するための鍵となります。

インデックス (Index) と複合主キー

Big Objectsを理解する上で最も重要な概念がインデックス (Index) です。Big Objectでは、レコードを識別し、クエリのパフォーマンスを確保するために、複数の項目を組み合わせた複合主キー (Composite Primary Key) としてインデックスを定義します。このインデックスは、Big Objectの作成時に定義する必要があり、一度作成すると変更することはできません。

インデックスは最大5つの項目で構成され、定義された項目の順序が極めて重要です。SOQLクエリを実行する際、WHERE句ではインデックスで定義された項目を、定義順の左から順にフィルタリング条件として指定する必要があります。 例えば、`Account__c`, `Interaction_Date__c`, `Event_Type__c` の順でインデックスを定義した場合、クエリでは最低でも `Account__c` を指定する必要があり、`Interaction_Date__c` だけで検索することはできません。このインデックス設計が、Big Objectsのパフォーマンスと使い勝手を決定づけます。

データアクセス

Big Objectsのデータは、Salesforceの標準UI(ユーザーインターフェース)には表示されません。レコードの作成、参照は主に以下のAPIベースの方法で行います。

  • Apex: Database.insertImmediate() を使って同期的にレコードを挿入したり、SOQLを使ってデータをクエリしたりできます。
  • SOQL (Salesforce Object Query Language): ApexやAPI経由でBig Objectのデータをクエリするための言語です。ただし、前述の通り、インデックスに基づいた厳格なフィルタリング条件が必須です。
  • Async SOQL (非同期SOQL): 数百万件以上のレコードを対象とした集計やデータ抽出など、大規模なクエリを実行するための仕組みです。クエリジョブを投入し、完了後に結果セットを取得します。
  • API: SOAP API, REST API, Bulk API 2.0 を使用してデータの挿入が可能です。

DML操作の制限

Big Objectsは、主に書き込みと読み取りに特化しています。そのため、DML (Data Manipulation Language) 操作には以下の制限があります。

  • Insert: insert 操作のみサポートされています。
  • Update, Delete, Upsert: これらの操作はサポートされていません。レコードを更新または削除する必要がある場合、一度データを抽出し、修正・除外した上で再挿入するなどの代替アプローチが必要です。

サポートされない機能

パフォーマンスとスケーラビリティを最優先するため、Big Objectsでは以下の標準Salesforce機能はサポートされていません。

  • トリガ
  • プロセスビルダーやフロー
  • 入力規則
  • 共有ルールやOWD(組織の共有設定)
  • 標準レポートとダッシュボード

これらの処理は、データをBig Objectに挿入する前のアプリケーション層で実装する必要があります。


示例代码

ここでは、Big Objectの定義からデータの挿入、クエリまでの具体的なコード例を紹介します。コードはSalesforceの公式ドキュメントに基づいています。

1. Big Objectの定義 (メタデータ)

Big Objectは、メタデータAPIまたはAnt移行ツールを使用してデプロイします。以下は、顧客のインタラクション履歴を格納する `Customer_Interaction__b` というBig Objectの定義ファイル (`.object` ファイル) の例です。

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <deploymentStatus>Deployed</deploymentStatus>
    <fields>
        <fullName>Account__c</fullName>
        <label>Account</label>
        <length>18</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>Interaction_Date__c</fullName>
        <label>Interaction Date</label>
        <required>true</required>
        <type>DateTime</type>
    </fields>
    <fields>
        <fullName>Event_Type__c</fullName>
        <label>Event Type</label>
        <length>255</length>
        <required>false</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>Description__c</fullName>
        <label>Description</label>
        <length>1000</length>
        <required>false</required>
        <type>LongTextArea</type>
        <visibleLines>3</visibleLines>
    </fields>
    <indexes>
        <fullName>CustomerInteractionIndex</fullName>
        <label>Customer Interaction Index</label>
        <fields>
            <name>Account__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
        <fields>
            <name>Interaction_Date__c</name>
            <sortDirection>DESC</sortDirection>
        </fields>
    </indexes>
    <label>Customer Interaction</label>
    <pluralLabel>Customer Interactions</pluralLabel>
</CustomObject>

解説:

  • `__b` というサフィックスは、Big ObjectのAPI参照名を示します。
  • `<indexes>` タグ内で複合主キーを定義します。この例では `Account__c` (昇順) と `Interaction_Date__c` (降順) でインデックスを構成しています。
  • このインデックス設計により、特定の取引先 (`Account__c`) のインタラクション履歴を、日付の新しい順に効率よく取得できます。

2. Apexによるデータ挿入

Big Objectへのレコード挿入は、通常のsObjectと同様のリストを作成し、`Database.insertImmediate()` メソッドを使用します。

// 挿入するBig Objectレコードのリストを作成
List<Customer_Interaction__b> interactions = new List<Customer_Interaction__b>();

// 1件目のレコード
Customer_Interaction__b interaction1 = new Customer_Interaction__b();
interaction1.Account__c = '001xx000003DHPxAAO'; // 取引先ID
interaction1.Interaction_Date__c = Datetime.newInstance(2023, 10, 26, 10, 0, 0);
interaction1.Event_Type__c = 'Webinar Viewed';
interaction1.Description__c = 'Attended the "Mastering Big Objects" webinar.';
interactions.add(interaction1);

// 2件目のレコード
Customer_Interaction__b interaction2 = new Customer_Interaction__b();
interaction2.Account__c = '001xx000003DHPxAAO'; // 同じ取引先ID
interaction2.Interaction_Date__c = Datetime.newInstance(2023, 10, 25, 14, 30, 0);
interaction2.Event_Type__c = 'Support Call';
interaction2.Description__c = 'Called support regarding a configuration issue.';
interactions.add(interaction2);

// Database.insertImmediateを使用して同期的にレコードを挿入
Database.SaveResult[] results = Database.insertImmediate(interactions);

// 結果をチェック
for (Database.SaveResult res : results) {
    if (res.isSuccess()) {
        System.debug('Successfully inserted Big Object record. ID: ' + res.getId());
    } else {
        for (Database.Error err : res.getErrors()) {
            System.debug('Error inserting Big Object record: ' + err.getStatusCode() + ': ' + err.getMessage());
        }
    }
}

解説:

  • Big Objectのレコードを挿入する際は、標準オブジェクトと異なり `Database.insert()` ではなく `Database.insertImmediate()` (同期) または `Database.insertAsync()` (非同期) を使用します。
  • ガバナ制限(DML行数など)は標準オブジェクトと同様に適用されます。

3. ApexによるSOQLクエリ

インデックスで定義した項目をWHERE句で指定して、Big Objectのデータをクエリします。

// 特定の取引先IDと日付範囲を指定してクエリを実行
String accountId = '001xx000003DHPxAAO';
Datetime startDate = Datetime.newInstance(2023, 10, 1, 0, 0, 0);

// インデックスの第一項目 (Account__c) と第二項目 (Interaction_Date__c) をフィルタ条件に使用
List<Customer_Interaction__b> interactions = [
    SELECT Account__c, Interaction_Date__c, Event_Type__c, Description__c
    FROM Customer_Interaction__b
    WHERE Account__c = :accountId
    AND Interaction_Date__c >= :startDate
    ORDER BY Interaction_Date__c DESC
    LIMIT 100
];

for (Customer_Interaction__b interaction : interactions) {
    System.debug('Event: ' + interaction.Event_Type__c + ' on ' + interaction.Interaction_Date__c);
}

解説:

  • `WHERE` 句でインデックスの第一項目である `Account__c` が `=` 演算子で指定されています。これは必須です。
  • 続けて、第二項目である `Interaction_Date__c` が範囲指定 (`>=`) で使用されています。
  • インデックスで定義されていない項目(例: `Event_Type__c`)を `WHERE` 句のフィルタ条件として直接使用することはできません。

4. Async SOQLによる大規模クエリ

Async SOQLは、大量のデータを扱うためのクエリ方法です。主にREST API経由で実行されますが、ここではクエリの例とその考え方を示します。

まず、以下のような集計クエリを考えます。これは、特定の期間内にインタラクションがあった取引先の数をイベントタイプ別に集計するものです。

-- これはAsync SOQLクエリの例であり、Developer Consoleでは直接実行できません。
-- REST API経由で `/services/data/vXX.X/jobs/query` エンドポイントにPOSTします。

SELECT Event_Type__c, COUNT(Account__c)
FROM Customer_Interaction__b
WHERE Interaction_Date__c > 2023-01-01T00:00:00Z
GROUP BY Event_Type__c

解説:

  • Async SOQLでは、標準のSOQLよりも柔軟な `WHERE` 句が許容される場合がありますが、基本的にはインデックスを活用することがパフォーマンスの鍵です。
  • このクエリは、Salesforceのバックグラウンドで非同期に実行されます。クエリを投入するとジョブIDが返され、そのIDを使ってジョブのステータスを確認し、完了後に結果をCSVファイルとしてダウンロードします。
  • Apexから実行する場合は、`HttpRequest` を使用してSalesforceのREST APIエンドポイントへコールアウトを行います。


注意事項

権限

Big Objectにアクセスするには、ユーザーのプロファイルまたは権限セットで適切なオブジェクト権限(参照、作成)が必要です。標準オブジェクトと同様に権限管理を行ってください。

API制限

Big Object自体は大量のデータを格納できますが、アクセス方法には制限があります。

  • SOQLガバナ制限: Apexから同期SOQLを実行する場合、返される行数(最大50,000行)などの標準的なガバナ制限が適用されます。
  • Async SOQL制限: 24時間あたりに実行できるAsync SOQLジョブの数には組織ごとの上限があります。詳細はSalesforceのドキュメントで確認してください。

インデックス設計の重要性

繰り返しになりますが、インデックス設計はBig Objectプロジェクトの成功を左右する最も重要な要素です。インデックスは後から変更できないため、設計段階で将来のクエリパターンを慎重に検討する必要があります。特にインデックスの第一項目は、データを絞り込むための最も主要なフィルタとなるため、カーディナリティ(値のばらつき)が高い項目を選択することが推奨されます。

エラーハンドリング

データ挿入時には、`Database.insertImmediate` の戻り値である `SaveResult` を確認し、エラー処理を適切に行う必要があります。複合主キーの制約に違反した場合(重複するキーの組み合わせでレコードを挿入しようとした場合)などはエラーが発生します。


まとめとベストプラクティス

Salesforce Big Objectsは、プラットフォーム上で大規模データを扱うための強力なソリューションです。しかし、その特性を正しく理解し、適切なシナリオで利用することが重要です。最後に、Big Objectsを成功させるためのベストプラクティスをまとめます。

  • 適切なユースケースを選択する:

    Big Objectsは、標準オブジェクトの完全な代替ではありません。データアーカイブ、イベントログ、読み取り専用の履歴データなど、UIやリアルタイムの自動化が不要な大規模データセットに限定して使用してください。
  • インデックスを慎重に設計する:

    データへのアクセス方法を決定づけるインデックスは、最も重要な設計項目です。将来必要となるクエリパターンをすべて洗い出し、最適な項目と順序を決定してください。
  • Async SOQLを積極的に活用する:

    大規模なデータセットに対する分析や集計、エクスポートには、同期SOQLではなくAsync SOQLを使用することが不可欠です。これにより、ガバナ制限を回避し、システムのパフォーマンスへの影響を最小限に抑えることができます。
  • データライフサイクルを計画する:

    Big Objectには `delete` 操作がないため、データのライフサイクル管理戦略を事前に計画しておく必要があります。例えば、インデックスに日付項目を含め、特定の期間のデータのみをクエリ対象とするなどの設計が考えられます。
  • 分析ツールとの連携を検討する:

    Big Objectのデータは標準レポートでは利用できないため、Tableau CRM (旧Einstein Analytics) や外部のBIツールと連携して可視化・分析するアーキテクチャを検討してください。

これらの原則とベストプラクティスに従うことで、Salesforce Big Objectsの能力を最大限に引き出し、増え続けるデータと共にスケールする、堅牢なデータアーキテクチャを構築することができるでしょう。

コメント