Salesforceデータアーカイブ戦略:パフォーマンスとコンプライアンスを最適化するための完全ガイド

執筆者:Salesforce アーキテクト


背景と適用シナリオ

Salesforceは、企業の顧客関係管理(CRM)の中心的なプラットフォームとして、日々膨大な量のデータを生成・蓄積しています。商談、ケース、活動履歴、カスタムオブジェクトのレコードなど、データが指数関数的に増加するにつれて、多くの企業が共通の課題に直面します。それは、データストレージの枯渇レポートや検索のパフォーマンス低下、そしてコンプライアンス要件の複雑化です。Salesforceの組織(Org)が成長し、成熟するにつれて、アクティブではない過去のデータを適切に管理する必要性が高まります。これが、Data Archiving (データアーカイブ) 戦略が不可欠となる理由です。

データアーカイブとは、本番環境からアクティブに使用されなくなったデータを、よりコスト効率の高い長期保存用のストレージに移動させるプロセスを指します。これにより、以下の重要な目的を達成できます。

  • パフォーマンスの最適化: 本番オブジェクトのレコード数を削減することで、SOQLクエリ、レポート、リストビューの実行速度が向上し、ユーザーエクスペリエンスが改善されます。特に、数百万件以上のレコードを持つオブジェクトでは、パフォーマンスへの影響が顕著になります。
  • ストレージコストの削減: Salesforceのデータストレージには上限があり、超過すると追加コストが発生します。不要なデータをアーカイブすることで、貴重なストレージ容量を解放し、コストを抑制できます。
  • コンプライアンスとガバナンスの遵守: GDPR(EU一般データ保護規則)やCCPA(カリフォルニア州消費者プライバシー法)などの規制では、データの保持期間に関する厳格なポリシーが定められています。アーカイブ戦略は、これらのData Retention Policy (データ保持ポリシー) を体系的に実行するための基盤となります。
  • システムのスケーラビリティ確保: 将来的なビジネスの成長を見据え、データ量の増加に対応できるスケーラブルなアーキテクチャを維持するためには、定期的なデータ整理が不可欠です。

本稿では、Salesforceアーキテクトの視点から、効果的なデータアーカイブ戦略の設計と実装について、その原理、具体的なアプローチ、ベストプラクティスを詳述します。

原理説明

Salesforceにおけるデータアーカイブ戦略は、単にデータを削除することではありません。それは、「どのデータを」「どこに」「どのように移動し」「どうやってアクセスするか」を定義する包括的な設計プロセスです。アーキテクチャを設計する際、主に2つのアプローチを検討します。

1. On-Platform Archiving (プラットフォーム内アーカイブ)

このアプローチは、Salesforceプラットフォーム内でデータを移動させる方法です。例えば、「Archived_Case__c」のようなカスタムオブジェクトを作成し、古いCaseレコードをそこに移動させます。

  • 長所: 実装が比較的容易で、追加のツールや外部システムが不要です。アーカイブされたデータもSalesforceの標準的なUIやレポート機能である程度アクセス可能です。
  • 短所: Salesforceのデータストレージを消費し続けるため、ストレージコスト削減という点では限定的です。また、アーカイブ用オブジェクトもレコード数が増えればパフォーマンスに影響を与える可能性があります。

2. Off-Platform Archiving (プラットフォーム外アーカイブ)

こちらが本格的なアーカイブ戦略の主流です。アクティブでないデータをSalesforceの外部にある、より安価で大容量のストレージシステムに移動させます。主な移動先として、以下のような選択肢があります。

  • Salesforce Big Objects: Salesforceプラットフォーム上で提供されるビッグデータストレージサービスです。数十億件のレコードを格納できるように設計されており、パフォーマンスへの影響を最小限に抑えながら、Salesforceエコシステム内でデータを保持できます。アーカイブデータへのアクセスは、主に Async SOQL (非同期SOQL) を使用します。
  • Heroku (Heroku Postgres): Heroku Connectを利用してSalesforceのデータをHeroku Postgresデータベースに同期・アーカイブします。リレーショナルデータベースの柔軟なクエリ機能を利用でき、Webアプリケーションから直接アクセスすることも可能です。
  • クラウドデータウェアハウス (AWS, Google Cloud, Azure): Amazon S3/Redshift, Google BigQuery, Azure Synapse Analyticsなどの外部データウェアハウスにデータを移動します。ETL (Extract, Transform, Load) ツール(例:MuleSoft, Informatica)を介してデータを抽出し、高度な分析や機械学習に活用する場合に適しています。

アーキテクトとしては、コスト、データへのアクセス頻度、クエリの複雑性、既存の技術スタック、コンプライアンス要件などを総合的に評価し、最適なアーカイブ先を選択する必要があります。多くの場合、Salesforceとの親和性が高く、比較的導入しやすい Big Objects が第一の候補となります。


実装アプローチとコード例

ここでは、最も代表的な「Big Objectsを活用したアーカイブ」の実装アプローチを、Batch Apexを使用したコード例とともに解説します。

シナリオ:クローズしてから2年以上経過した「ケース(Case)」レコードを、「Archived_Case__b」というBig Objectに移動し、元のCaseレコードを削除する。

ステップ1:Big Objectの定義

まず、アーカイブデータを格納するためのBig Objectを定義します。ケースの主要なフィールド(CaseNumber, Subject, Status, CreatedDate, ClosedDateなど)と、元のCaseレコードIDを保持するフィールド(Original_Case_ID__c)を含めます。

ステップ2:Batch Apexクラスの作成

次に、アーカイブプロセスを実行するBatch Apexクラスを作成します。このバッチ処理は、(1)アーカイブ対象のレコードをクエリし、(2)Big Objectに挿入し、(3)元のレコードを削除する、という3つのステップで構成されます。

示例代码

以下のコードは、指定された条件に一致するCaseレコードをBig Objectにアーカイブし、元のレコードを削除するBatch Apexクラスです。このコードは、Salesforce DeveloperドキュメントのBatch ApexおよびBig Objectsのベストプラクティスに基づいています。

global class ArchiveCasesToBigObjectBatch implements Database.Batchable<sObject> {

    // バッチ処理の対象となるレコードを決定するSOQLクエリ
    global final String query;

    // コンストラクタでクエリを初期化
    global ArchiveCasesToBigObjectBatch() {
        // 2年前の日付を計算
        Date twoYearsAgo = System.today().addYears(-2);
        // クローズ済みで、かつクローズ日が2年以上前のケースを対象とする
        this.query = 'SELECT Id, CaseNumber, Subject, Status, Priority, CreatedDate, ClosedDate, Description FROM Case WHERE IsClosed = true AND ClosedDate <= :twoYearsAgo';
    }

    // バッチ処理の開始時に呼び出されるメソッド
    // 対象レコードのQueryLocatorを返す
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator(this.query);
    }

    // 各バッチ(レコードのチャンク)ごとに呼び出されるメソッド
    global void execute(Database.BatchableContext BC, List<Case> scope) {
        List<Archived_Case__b> casesToArchive = new List<Archived_Case__b>();
        
        // 処理対象のCaseレコードをループ
        for (Case c : scope) {
            // Big Objectのレコードを作成し、Caseのフィールドをマッピング
            Archived_Case__b archivedCase = new Archived_Case__b(
                Original_Case_ID__c = c.Id, // 元のレコードIDを保存
                Case_Number__c = c.CaseNumber,
                Subject__c = c.Subject,
                Status__c = c.Status,
                Priority__c = c.Priority,
                Created_Date__c = c.CreatedDate,
                Closed_Date__c = c.ClosedDate,
                Description__c = c.Description
            );
            casesToArchive.add(archivedCase);
        }

        // Big Objectへのレコード挿入
        // Database.insertImmediateは、Big Objectへの同期的な挿入を可能にする
        if (!casesToArchive.isEmpty()) {
            List<Database.SaveResult> saveResults = Database.insertImmediate(casesToArchive);

            // 挿入に成功した元のCaseレコードを特定するためのIDリスト
            List<Id> idsToDelete = new List<Id>();
            
            // 挿入結果を確認
            for (Integer i = 0; i < saveResults.size(); i++) {
                Database.SaveResult sr = saveResults[i];
                if (sr.isSuccess()) {
                    // 成功した場合、対応する元のCaseのIDを削除リストに追加
                    // sObjectリストとSaveResultリストの順序は一致する
                    idsToDelete.add(scope[i].Id);
                } else {
                    // Big Objectへの挿入に失敗した場合のエラー処理
                    for(Database.Error err : sr.getErrors()) {
                        System.debug('Error archiving Case ' + scope[i].Id + ': ' + err.getStatusCode() + ': ' + err.getMessage());
                    }
                }
            }
            
            // 挿入が成功したレコードのみを削除
            if (!idsToDelete.isEmpty()) {
                Database.delete(idsToDelete, false); // falseを指定して部分的な成功を許容
            }
        }
    }

    // すべてのバッチ処理が完了した後に呼び出されるメソッド
    global void finish(Database.BatchableContext BC) {
        // 完了通知のメール送信などの処理をここに追加
        System.debug('Case archiving process completed.');
        // 例: 非同期Apexジョブのステータスを確認
        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email 
                            FROM AsyncApexJob WHERE Id = :BC.getJobId()];
        // 管理者にメールで結果を通知
        // (メール送信ロジックは省略)
    }
}

このバッチは、スケジューラブルなApexクラスから定期的に(例:毎週末)実行することで、アーカイブプロセスを自動化できます。

注意事項

データアーカイブ戦略を実装する際には、アーキテクトとして以下の点を慎重に検討する必要があります。

  • Data Integrity (データ整合性):

    親子関係にあるデータをアーカイブする際は特に注意が必要です。例えば、Caseに紐づくEmailMessageやCaseCommentをどう扱うか、事前に定義しなければなりません。主従関係(Master-Detail Relationship)の主レコードを削除すると、従レコードも自動的に削除されるため、関連するすべてのデータを一貫してアーカイブする設計が求められます。

  • Permissions and Governance (権限とガバナンス):

    アーカイブされたデータへのアクセス権限を誰が持つのかを明確に定義する必要があります。Big Objectsの場合、プロファイルや権限セットでオブジェクトレベルの権限を制御できますが、外部データストアの場合は、そのシステム独自の認証・認可メカニズムを設計・管理しなければなりません。

  • API Limits (API制限):

    大量のデータを一度に処理すると、SOQLクエリのガバナ制限やDMLステートメントの制限、APIコール数の上限に達する可能性があります。Batch Apexはこれらの制限を回避するために設計されていますが、バッチサイズ(デフォルト200)を適切に調整し、Bulk API 2.0の利用も検討することが重要です。

  • Error Handling and Rollback (エラーハンドリングとロールバック):

    アーカイブプロセス中にエラーが発生した場合の対処法を設計に組み込む必要があります。例えば、Big Objectへの書き込みが失敗したのに、元のSalesforceレコードが削除されてしまうとデータが失われます。コード例のように、挿入が成功したレコードのみを削除するロジックや、失敗した処理を記録して再試行するメカニズムが不可欠です。

  • Data Retrieval (データ復元):

    アーカイブされたデータをユーザーがどのように閲覧・利用するかを定義しておく必要があります。Big Objectsのデータは標準UIでは表示できないため、Async SOQLを実行するカスタムUI(Lightning Web Componentなど)を開発するか、Tableau CRMなどの分析ツールと連携させる必要があります。また、法的要請などでデータを本番環境に復元(リストア)する必要がある場合のプロセスも事前に設計しておくべきです。

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

Salesforceのデータアーカイブ戦略は、単なる技術的な課題解決ではなく、組織のデータガバナンスとシステム全体の健全性を長期的に維持するための重要な経営戦略です。アーキテクトとして、以下のベストプラクティスを推奨します。

  1. ポリシーの先行定義:技術的な実装に取り掛かる前に、ビジネス部門や法務部門と連携し、明確なデータ保持・アーカイブポリシーを文書化します。どのデータを、いつ、どのくらいの期間保持し、いつアーカイブまたは削除するのかを定義します。
  2. 現状分析と対象の特定:Salesforce Optimizerやストレージ利用状況レポートを活用して、どのオブジェクトが最もストレージを消費し、パフォーマンスに影響を与えているかを分析します。ROI(投資対効果)が最も高いオブジェクトからアーカイブに着手します。
  3. 適切なソリューションの選択:データの性質(構造、量)、アクセス要件、コスト、セキュリティ、既存の技術スタックを総合的に評価し、Big Objects、Heroku、外部データウェアハウスなど、最適なアーカイブ先を選択します。
  4. 自動化と監視の設計:アーカイブプロセスは手動ではなく、スケジュールされたバッチ処理やETLジョブによって完全に自動化します。また、プロセスの実行状況、成功・失敗を監視し、異常があれば管理者に通知する仕組みを構築します。
  5. アクセス手段の確保:アーカイブは「データの塩漬け」ではありません。コンプライアンス監査や過去の傾向分析など、必要な時にデータにアクセスできる手段を必ず用意します。Salesforce Connectを利用して外部データをSalesforce UI上に表示させることも有効な選択肢です。
  6. 段階的な導入:全社的なアーカイブ戦略を一気に展開するのではなく、まずは影響の少ない単一のオブジェクトを対象にパイロットプロジェクトを実施し、プロセスを検証・改善してから横展開します。

適切なデータアーカイブ戦略を導入することで、Salesforceプラットフォームのパフォーマンスを最大化し、コストを最適化し、コンプライアンスを遵守することができます。これは、持続可能でスケーラブルなSalesforce環境を維持するための、アーキテクトにとっての重要な責務です。

コメント