リアルタイムデータ連携を解き放つ:Salesforce Connect 活用ガイド(Salesforce コンサルタントの視点から)

概要とビジネスシーン

Salesforce Connect は、Salesforce 内にデータをコピーすることなく、外部システムに存在するデータをリアルタイムで参照・操作することを可能にする画期的な機能です。これにより、Salesforce のデータストレージを消費せずに常に最新の情報を利用でき、顧客360度ビュー(Customer 360 View)の完成度を高めることができます。

実際のビジネスシーン

シーンA:小売業界 - オムニチャネル顧客体験

  • ビジネス課題:顧客がオンラインストアで商品を購入した後、店舗で返品や問い合わせを行う際、Salesforce のサービス担当者が EC サイトのリアルタイムな注文履歴や在庫状況を即座に把握できない。
  • ソリューション:Salesforce Connect を利用して、EC サイトの注文管理システム(OMS)と Salesforce を連携。EC サイトの注文データを「外部オブジェクト(External Object)」として Salesforce Service Cloud に表示。
  • 定量的効果:顧客対応時間が 20% 短縮され、顧客満足度スコア(CSAT)が 15% 向上。データ入力ミスも削減。

シーンB:製造業界 - 精度の高い見積もりと CPQ

  • ビジネス課題:ERP システムにある最新の製品マスタ、在庫、価格情報を Salesforce CPQ(Configure, Price, Quote)で利用する際、バッチ同期によるタイムラグがあり、見積もりが古い情報に基づいて作成されてしまうリスクがある。
  • ソリューション:Salesforce Connect の OData アダプタを利用し、ERP システムの製品・在庫データを外部オブジェクトとして Salesforce CPQ でリアルタイム参照。
  • 定量的効果:見積もりプロセスの手戻りが 30% 削減され、営業担当者が常に最新の製品情報に基づいた正確な見積もりを迅速に提供可能に。

シーンC:金融業界 - 顧客の総合的な信用状況把握

  • ビジネス課題:顧客の与信情報や口座履歴が複数のレガシーシステムに分散しており、Salesforce 上で顧客とコミュニケーションを取る際に、リアルタイムな信用状況を確認するために別のシステムへログインが必要。
  • ソリューション:カスタムアダプタを用いて、既存の与信管理システムや口座管理システムと Salesforce を連携。顧客の信用スコアや取引履歴を外部オブジェクトとして表示。
  • 定量的効果:顧客対応時の情報収集時間が 25% 短縮され、よりパーソナライズされた提案が可能に。コンプライアンス遵守も強化。

技術原理とアーキテクチャ

Salesforce Connect は、Salesforce が外部システムに存在するデータを「外部オブジェクト」として扱うことで、あたかも Salesforce 内の標準・カスタムオブジェクトであるかのように見せる技術です。この連携は、以下の主要な「アダプタ(Adapter)」を通じて行われます。

  • OData アダプタ:Open Data Protocol を使用して RESTful なデータソースに接続します。OData 2.0、4.0 がサポートされています。設定ベースで迅速な実装が可能です。
  • Salesforce Connect カスタムアダプタ:Apex コードを使用して、任意の外部データソース(SOAP/REST API、データベースなど)に接続するためのカスタムロジックを実装します。最も柔軟性が高いオプションです。
  • Salesforce Connect クロス組織アダプタ:別の Salesforce 組織のデータを外部オブジェクトとして表示します。

基礎的な動作メカニズムとしては、Salesforce ユーザーが外部オブジェクトにアクセスすると、Salesforce Connect は設定された外部データソースを通じて外部システムへリアルタイムにクエリを発行し、その結果を Salesforce に表示します。データは Salesforce のストレージには保存されません。

主要コンポーネントと依存関係

  • 外部データソース (External Data Source):Salesforce が接続する外部システムの定義(接続URL、認証情報、アダプタタイプなど)。
  • 外部オブジェクト (External Object):外部データソース上のテーブルやエンティティを Salesforce オブジェクトとしてマッピングしたもの。
  • 外部オブジェクトの項目 (External Object Fields):外部オブジェクトの各項目。外部システムのデータ型と Salesforce のデータ型をマッピングします。

データフロー

ステップ 説明 関連コンポーネント
1. ユーザーアクセス Salesforce ユーザーが外部オブジェクトのレコード、リストビュー、レポートなどにアクセスします。 Salesforce UI
2. クエリ発行 Salesforce Connect は、外部データソース定義に基づいて外部システムへデータクエリを生成・発行します。 外部オブジェクト、外部データソース
3. 外部システム処理 外部システムは Salesforce からのクエリを受け取り、該当するデータを検索・処理します。 外部システム (OData エンドポイント、カスタム API など)
4. データ返却 外部システムは、クエリ結果を Salesforce が理解できる形式(OData、JSON、XMLなど)で返却します。 外部システム
5. Salesforce表示 Salesforce Connect は受け取ったデータを外部オブジェクトとして Salesforce UI に表示します。 外部オブジェクト

ソリューション比較と選定

ソリューション 適用シーン パフォーマンス Governor Limits 複雑度
Salesforce Connect リアルタイムデータ参照、外部データのコピー不要、ストレージ消費削減、常に最新データが必要な場合。 外部システムの応答速度に依存。キャッシュ利用で改善の余地あり。 主にコールアウト制限、SOQLクエリ制限。Salesforceのストレージ制限には影響なし。 ODataは設定ベースで低。カスタムアダプタはApex開発が必要で中〜高。
ETLツール (例: MuleSoft, Informatica) データ移行、複雑なデータ変換・統合、データウェアハウス構築、バッチ処理、データ同期。 バッチ処理では高いスループット。リアルタイム同期も可能だが別途設定・構築が必要。 Salesforceへのデータ挿入/更新時に発生。APIコール制限など。 ツールと要件により中〜高。
Apex Callout + カスタムオブジェクト 外部データを取り込み、Salesforce内で複雑なビジネスロジックや集計を行う必要がある場合。 Apexコードの最適化と外部システムの応答速度に依存。データコピーが発生。 Apex実行時間、メモリ、SOQLクエリ、DML、Callout回数、Heapサイズなど、Salesforceの厳密なGovernor Limitsに直接影響。 Apex開発が必要で高。

Salesforce Connect を使用すべき場合

  • ✅ 外部データが頻繁に更新され、常に最新の情報が Salesforce に表示される必要がある場合。
  • ✅ 外部データを Salesforce のストレージにコピーしたくない、またはストレージコストを削減したい場合。
  • ✅ 外部システムが OData エンドポイントを提供している、または Apex で接続可能な API を持っている場合。
  • ✅ Salesforce 内で外部データに対する複雑なデータ操作やリレーションシップが限定的で、主に参照が目的の場合。
  • ✅ Salesforce UI を通じて外部データをリアルタイムに検索、表示、または(書き込み可能設定で)編集したい場合。

不適用シーン

  • ❌ 外部データソースのパフォーマンスが非常に低く、リアルタイムでの応答が期待できない場合。
  • ❌ 外部データに対して、Salesforce の強力なSOQLクエリ(特に結合や複雑な集計)を多用したい場合。
  • ❌ 外部データが大量であり、Salesforce のレポート機能で単独で複雑な分析を行う必要がある場合(外部オブジェクト単体では制限があるため)。
  • ❌ 外部システム側の API が不安定、または可用性が低い場合(Salesforce からのアクセスも同様に不安定になるため)。

実装例

ここでは、Salesforce Connect カスタムアダプタを用いて、外部システムから簡単なリストをフェッチする Apex コードの例を示します。この例は、公式ドキュメント Apex Connectors GuideSampleAdapter を基に、基本的なデータフェッチロジックに焦点を当てて簡略化しています。

// DataSource.Provider インターフェースを実装し、外部データソースへの接続を管理
public class SampleCustomAdapterProvider implements DataSource.Provider {

    // 接続のサポート対象能力を定義
    public List<DataSource.Capability> getCapabilities() {
        // Query (データの読み取り) と Search (検索) をサポート
        return new List<DataSource.Capability> {
            DataSource.Capability.Query,
            DataSource.Capability.Search
        };
    }

    // 接続オブジェクトのインスタンスを返却
    public DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) {
        // ここで接続パラメータ (認証情報など) を処理し、DataSource.Connection の実装を返す
        // この例ではシンプルに SampleCustomAdapterConnection をインスタンス化
        return new SampleCustomAdapterConnection();
    }

    // メタデータ (外部オブジェクトのスキーマ) の生成を定義
    public DataSource.Metadata getMetadata() {
        // メタデータを返却するが、この例では接続が動的にメタデータを取得すると仮定
        // 通常はここで外部オブジェクトの構造を定義する
        return null; // ⚠️ 公式ドキュメントのより詳細な実装では、ここでスキーマを定義します
    }
}

// DataSource.Connection インターフェースを実装し、外部システムとの実際の通信を行う
public class SampleCustomAdapterConnection implements DataSource.Connection {

    // 外部オブジェクトのスキーマ定義を返却
    public DataSource.Table getTable(String tableName) {
        // テーブル名 'SampleItems' のスキーマを定義
        if (tableName == 'SampleItems') {
            DataSource.Table table = DataSource.Table.get(tableName);
            table.setDisplayName('サンプルアイテム');
            
            // ID項目(主キー)を定義
            DataSource.Column idCol = DataSource.Column.url('Id');
            idCol.setDisplayName('ID');
            idCol.setFilterable(true); // フィルタリング可能
            idCol.setSortable(true);   // ソート可能
            table.addColumn(idCol);

            // Name項目を定義
            DataSource.Column nameCol = DataSource.Column.text('Name', 255);
            nameCol.setDisplayName('アイテム名');
            nameCol.setFilterable(true);
            nameCol.setSortable(true);
            table.addColumn(nameCol);

            // Description項目を定義
            DataSource.Column descCol = DataSource.Column.text('Description', 255);
            descCol.setDisplayName('説明');
            table.addColumn(descCol);

            return table;
        }
        return null;
    }

    // 外部オブジェクトのリスト (スキーマ) を返却
    public List<DataSource.Table> getTables() {
        List<DataSource.Table> tables = new List<DataSource.Table>();
        tables.add(getTable('SampleItems')); // 'SampleItems' テーブルを追加
        return tables;
    }

    // データのクエリを実行 (Salesforce からの SOQL に対応)
    public void query(DataSource.QueryContext context) {
        // 実際の外部システムへのコールアウトをここで行う
        // 例として、ハードコードされたデータを返す
        List<Map<String, Object>> results = new List<Map<String, Object>>();

        // 外部システムから取得したデータを Map として表現
        results.add(new Map<String, Object>{
            'Id' => '1001',
            'Name' => 'Item A',
            'Description' => 'Description for Item A'
        });
        results.add(new Map<String, Object>{
            'Id' => '1002',
            'Name' => 'Item B',
            'Description' => 'Description for Item B'
        });
        results.add(new Map<String, Object>{
            'Id' => '1003',
            'Name' => 'Item C',
            'Description' => 'Description for Item C'
        });

        // QueryContext に結果を追加
        for (Map<String, Object> row : results) {
            context.addRow(row);
        }
    }

    // データの検索を実行 (Salesforce のグローバル検索に対応)
    public void search(DataSource.SearchContext context) {
        // searchメソッドは、グローバル検索が外部オブジェクトを含む場合に呼び出される
        // queryメソッドと同様に、外部システムに検索クエリを送り、結果を返す
        query(context); // この例ではシンプルに query メソッドを呼び出す
    }

    // データ作成、更新、削除のメソッド(Writable External Objects で必要)
    // public void create(DataSource.CreateContext context) { /* ... */ }
    // public void update(DataSource.UpdateContext context) { /* ... */ }
    // public void delete(DataSource.DeleteContext context) { /* ... */ }
}

実装ロジックの解析:

  1. SampleCustomAdapterProvider クラス
    • DataSource.Provider インターフェースを実装し、Salesforce に対してこのカスタムアダプタの存在を宣言します。
    • getCapabilities() メソッドで、このアダプタがサポートする操作(クエリ、検索など)を定義します。
    • getConnection() メソッドで、実際に外部システムと通信を行う DataSource.Connection インターフェースを実装したクラスのインスタンスを返します。
  2. SampleCustomAdapterConnection クラス
    • DataSource.Connection インターフェースを実装し、外部データソースへの具体的な接続とデータのやり取りを処理します。
    • getTables() および getTable() メソッドは、外部データソースが提供するテーブル(Salesforce の外部オブジェクトに相当)のスキーマ(項目名、データ型など)を Salesforce に通知します。
    • query(DataSource.QueryContext context) メソッドが、外部オブジェクトへの SOQL クエリが実行された際に呼び出されます。このメソッド内で、実際に HTTP コールアウトなどを介して外部システムへクエリを送信し、結果を context.addRow() で Salesforce に返します。
    • search(DataSource.SearchContext context) メソッドは、Salesforce のグローバル検索が外部オブジェクトに対して実行された際に呼び出されます。
    • データの作成・更新・削除をサポートする場合は、create()update()delete() メソッドも実装する必要があります(Writable External Objects)。

注意事項とベストプラクティス

権限要件

  • 外部データソースへのアクセス権限:プロファイルまたは権限セットで、該当する「外部データソース(External Data Source)」への「有効化(Enabled)」アクセスが必要です。
  • 外部オブジェクトの権限:「外部オブジェクト(External Object)」への参照、作成、編集、削除権限が、プロファイルまたは権限セットで付与されている必要があります。

Governor Limits (2025年最新版)

Salesforce Connect を利用する際も、間接的に Apex の Governor Limits の影響を受けます。特にカスタムアダプタを使用する場合に注意が必要です。

  • Apex Callout タイムアウト:各コールアウトは最大 120 秒でタイムアウトします。外部システムの応答がこれを超えるとエラーになります。
  • 同期 Apex トランザクションでのコールアウト数:1つの同期 Apex トランザクションで実行できるコールアウトは最大 100 回です。
  • 外部データソースのクエリ行数:Salesforce Connect のクエリは、デフォルトで最大 2,000 行までしか取得できません。この制限は外部データソースの設定で変更可能ですが、パフォーマンスに影響を与える可能性があります。
  • 外部オブジェクトの検索結果制限:Salesforce グローバル検索で外部オブジェクトから返される結果も制限される場合があります。
  • 外部オブジェクトあたりの項目数:外部オブジェクトは最大 100 個のカスタム項目を持つことができます。

エラー処理

  • 外部システム障害:外部システムがダウンしている、または応答が遅い場合、Salesforce UI にエラーメッセージが表示されます。カスタムアダプタでは、Apex の try-catch ブロックを使用して、コールアウトのエラー(例: CalloutException)を適切に捕捉し、ユーザーフレンドリーなメッセージを返す、または代替処理を行う必要があります。
  • タイムアウト処理:長時間の応答を防ぐため、Apex コールアウトで明示的にタイムアウトを設定することを検討してください。
  • ロギング:カスタムアダプタ内で発生したエラーは、Apex Debug Log やカスタムロギングメカニズムを通じて詳細に記録し、デバッグとトラブルシューティングを容易にすることが重要です。

パフォーマンス最適化

  1. 外部データソースの最適化:Salesforce Connect のパフォーマンスは、外部システムの応答速度に大きく依存します。外部データソース側のデータベースクエリ、APIエンドポイントの処理速度を可能な限り最適化してください。インデックスの適用は必須です。
  2. 必要な項目のみをクエリ:外部オブジェクトへの SOQL クエリでは、必要な項目のみを選択するように心がけてください(例: SELECT Id, Name FROM ExternalObject__x)。不要な項目をフェッチすると、データ転送量が増加し、パフォーマンスが低下します。
  3. フィルタリングとソートの活用:外部オブジェクトの定義でフィルタリング可能(Filterable)およびソート可能(Sortable)な項目を適切に設定し、Salesforce からのクエリでこれらの条件を最大限に活用してください。これにより、外部システム側でデータを効率的に絞り込むことができます。
  4. ページネーションの実装:大量のデータを扱う場合、カスタムアダプタ内でページネーションを実装し、一度に取得するレコード数を制限することで、メモリ消費とネットワーク負荷を軽減し、パフォーマンスを向上させることができます。

よくある質問 FAQ

Q1:Salesforce Connect で外部データを Salesforce 内で編集(作成・更新・削除)できますか?

A1:はい、可能です。Salesforce Connect は「書き込み可能外部オブジェクト(Writable External Objects)」をサポートしています。これを有効にするには、外部データソースと外部オブジェクトの設定で「書き込みを有効化(Enable Writebacks)」をチェックし、カスタムアダプタの場合は create(), update(), delete() メソッドを実装する必要があります。

Q2:外部オブジェクトのデータは Salesforce の標準検索やレポートで利用できますか?

A2:外部オブジェクトは、デフォルトでは標準のグローバル検索の対象外です。ただし、「Salesforce Global Search for Salesforce Connect」を有効にすることで、外部オブジェクトのデータも検索対象に含めることができます。レポートについては、標準オブジェクトとのリレーションシップを定義することで、結合レポートを作成できますが、外部オブジェクト単体での複雑なレポート作成には一部制限があります。

Q3:Salesforce Connect のパフォーマンスの問題をデバッグするにはどうすればよいですか?

A3:パフォーマンス問題のデバッグには、主に以下の方法があります。

  • Salesforce Debug Log:カスタムアダプタを使用している場合、Apex のデバッグログで外部システムへのコールアウト時間や処理時間を確認できます。
  • 外部システムのログ:外部システム側の API アクセスログやデータベースクエリログを確認し、Salesforce からのクエリがどのように処理されているか、ボトルネックがないかを特定します。
  • 外部オブジェクトの使用状況レポート:Salesforce の設定メニューから外部オブジェクトの使用状況に関するレポートを生成し、コールアウト回数やエラー率を監視できます。


まとめと参考資料

Salesforce Connect は、外部データソースとのリアルタイムな連携を実現し、Salesforce の可能性を大きく広げる強力な機能です。ストレージ消費を抑えながら常に最新の情報を参照できるため、データの一貫性を保ち、顧客360度ビューの構築に不可欠な要素となります。OData、カスタムアダプタ、クロス組織アダプタの選択肢があり、ビジネス要件と外部システムの特性に応じて最適なアプローチを選ぶことが重要です。パフォーマンス、Governor Limits、適切なエラー処理を常に考慮し、堅牢で効率的な統合ソリューションを構築しましょう。

公式リソース

コメント