Force.com のマルチテナントアーキテクチャ

Force.com の仕組みを学ぶ

Forcedotcom-multitenant-architecture-wp-thumb.png

Force.com は、業界最高水準のクラウドアプリケーション開発プラットフォームであり、現在、10 万を超える組織と 22 万以上の展開済みアプリケーションをサポートしています。企業や SaaS ベンダー (SaaS: Sofware-as-a-Service: サービスとしてのソフトウェア) は、このプラットフォームを利用して、堅牢で信頼性の高い、インターネットスケールのアプリケーションを配布しています。Force.com の基盤は、マルチテナントアプリケーションを実現するメタデータ駆動型のソフトウェアアーキテクチャであり、これにより大規模ユーザの大量の需要に対応しています。この記事では、あらゆるタイプのアプリケーションにスピード、拡張性、セキュリティを提供する Force.com プラットフォームのテクノロジーについて解説します。

クラウドコンピューティング

クラウドコンピューティングは、エンタープライズクラスのコンピューティングリソースを低コストで瞬時に利用することを可能にし、2000 年以降、IT 業界に革命的な変化をもたらしました。クラウドでは、IT リソースに容易にアクセスできます。必要なリソースを必要なタイミングで利用することが可能で、リソースの提供メカニズムを管理する煩わしさからも解放されます。クラウドコンピューティングによって、従来の業務が今までになくシンプルで容易になっています。

マルチテナント

マルチテナントは、クラウドコンピューティングにおいて、低コストで安全に IT リソースを共有するために活用される重要なテクノロジーです。その仕組みは、マンションの建物に例えるとわかりやすいでしょう。マンションでは、複数の居住者が、設備を共有しながら建物をコスト効率よく利用しています。それぞれの部屋は壁やドアによって区切られ、プライバシーが確保されています。同様に、クラウドでは、マルチテナントテクノロジーによって、複数のアプリケーションやテナント (企業、組織など) が IT リソースを安全に共有しています。テナントの分離には、仮想化ベースのアーキテクチャや、カスタムのソフトウェアアーキテクチャが使われます。

このマルチテナントによって、IT 部門のアプリケーション提供の生産性は飛躍的に向上します。さらに、あらゆる処理が透過的に実行されるため、クラウドを利用する側のユーザ (CIO、CTO、システムアーキテクト、開発者など) が煩わされることもほとんどありません。ではこれから、Salesforce Platform の中核テクノロジーである Force.com を支えるすぐれた設計について、詳しく紹介します。

Force.com アーキテクチャの概要

Force.com は、高い実績を誇るクラウドアプリケーション開発プラットフォームです。セールスフォース・ドットコムのクラウドアプリケーション (Sales Cloud、Service Cloud など) や、顧客企業がビジネスニーズを満たすために開発するカスタムアプリケーションは、この Force.com によって支えられています。この後のセクションでは、Force.com プラットフォームの設計の主な特徴を簡単に説明します。

マルチテナントカーネル

Force.com は、クラウドコンピューティング向けの最新型の PaaS (Platform as a Service: サービスとしてのプラットフォーム) であり、マルチテナントが設計のベースになっています。のちほど、Force.com の実績を数値で示しますが、このマルチテナントアプローチにより、従来のアプリケーション開発プラットフォームをはるかに超える性能を実現しています。

従来のアプリケーション開発プラットフォームの基盤になっているのは、リレーショナルデータベース管理システム (RDBMS: Relational Database Management System) です。その基本的な仕様は、1970 年代から 1980 年代にかけて設計されたもので、各企業での自社運用型アプリケーションの展開をサポートするのがそもそもの目的でした。システムカタログ、キャッシュメカニズム、クエリオプティマイザ、アプリケーション開発機能といった RDBMS の柱となるメカニズムは、シングルテナントアプリケーションのサポートに特化した設計になっており、環境に応じてチューニングされたホストオペレーティングシステムと物理ハードウェア上で実行されます。標準の RDBMS でマルチテナント型のクラウドデータベースサービスを開発するとしたら、相当の時間を費やさない限り、必ず仮想化が必要になります。そして残念なことに、たいていの場合、ハイパーバイザーで発生する追加のオーバーヘッドによって RDBMS のパフォーマンスは低下します。

Fdc-mt-rdbms-compare.png

一方 Force.com では、カスタムのリレーショナルデータベーススキーマをはじめとするさまざまな永続化テクノロジーを組み合わせて使用しています。これらは最初からクラウドやマルチテナントを想定して設計されているため、仮想化は必要ありません。このすぐれたアーキテクチャには大きなメリットがあります。Force.com は、クラウドアプリケーション開発プラットフォームとして次に示すような確固たる実績を確立しており、その信頼性と安全性を高く評価されています。

  • 10 万社を超える企業が利用
  • 22 万件以上のアプリケーションを実行
  • ユーザ数は 300 万人
  • 四半期当たり 600 億件のトランザクションを処理。1 日で 10 億件を超えることもあり
  • 平均応答時間は 300 ミリ秒を切る
  • 平均稼働率は 99.9% 超

Force.com のシステムパフォーマンスと可用性に関する最新情報は、trust.salesforce.com を参照してください。

メタデータ駆動型のカーネル

Force.com のような、クラウドサービス向けに設計されたマルチテナント型のプラットフォームを実現するのは容易なことではありません。信頼性や拡張性を備えており、テナントごとのカスタマイズが可能であり、ダウンタイムなしでアップグレードを実行でき、さらに、セキュリティやスピードも必要になります。具体的には、テナント固有のデータを、他のテナントによるアクセスを回避しながら、共有データベースに安全に保存できなくてはいけません。また、他のテナントに影響を与えることなく、スキーマオブジェクトやアプリケーションのユーザインターフェースをリアルタイムで柔軟にカスタマイズできることも必要です。そのほか、テナントのスキーマに影響を与えずにシステムのコードベースにパッチやアップグレードを適用する方法、サービス利用者が急増してもシステムの応答時間を低下させない方法なども検討しなければなりません。

このようなマルチテナントに固有の課題には、静的コンパイル型のシステムでは対応できません。クラウドを想定したマルチテナントプラットフォームは、各テナントとそのテナントのユーザからのさまざまなニーズに対応するため、本質的に動的で、ポリモーフィック (多態的) であることが必要です。

こうした理由から、Force.com のコアテクノロジーでは、「データに関するデータ」であるメタデータからすべてのアプリケーションデータを生成するランタイムエンジンを採用しています。Force.com のメタデータ駆動型アーキテクチャは厳密に定義されており、コンパイル対象のランタイムエンジン (カーネル)、テナントのデータ、各アプリケーションを記述するメタデータがそれぞれ明確に分離されています。こうした構造により、システムカーネル、テナント固有のアプリケーションやスキーマなどを個別に更新し、他の領域への影響を回避しています。

Fdc-mt-metadata-driven-kernel.png

Force.com が提供するすべての論理データベースオブジェクトは、内部的にはメタデータを使って管理されています。オブジェクト (従来のリレーショナルデータベースの「テーブル」に相当)、項目、ストアドプロシージャ、データベーストリガなどは、すべて Force.com の UDD (Universal Data Dictionary: 汎用データ辞書) にメタデータとして格納される抽象的な構成概念です。たとえば、ユーザが新しいアプリケーションオブジェクトを定義したり手続き型のコードを記述したりする場合、Force.com では、データベースにテーブルを作成したりコードをコンパイルしたりするのではなく、メタデータを格納します。実行時には、プラットフォームのエンジンがこのメタデータを使用して仮想アプリケーションコンポーネントを生成します。ユーザがアプリケーションスキーマに変更やカスタマイズ (オブジェクト内の項目の修正など) を加えた場合も、更新されるのは対応するメタデータのみであり、他の領域に影響が及ぶことはありません。

メタデータは Force.com アプリケーションにとって重要な構成要素であり、ランタイムエンジンではメタデータに対するアクセスを常に最適化する必要があります。アクセスが集中すると、サービスの拡張性に支障を来たす可能性が生じます。Force.com では、この点がボトルネックにならないよう、高度かつ強力なメタデータキャッシュを用意し、直前に使われたメタデータをメモリに保存することで、ディスク I/O とコードの再コンパイルによるパフォーマンスへの影響を抑え、アプリケーションの応答速度を上げています。

多言語間の永続性

Force.com では、複数の異なるデータ永続化テクノロジーを組み合わせて最適化することによって多言語間の永続性を実現しており、これにより、あらゆるアプリケーションやデバイスをサポートします。他のプラットフォームのように、いくつものシステムを統合、管理、テスト、サポートしようと試みて頭を抱えるようなことはありません。1 つの API を開発すればそれで済みます。状況にもっとも適した永続化機能のタイプを検討する必要もありません。次の図に、Force.com の主な永続化テクノロジーを示します。

Fdc-mt-poly-persist.png

トランザクションエンジンは Force.com の柱となる機能です。Force.com では、マルチテナントに最適化されたデータモデルを備えたリレーショナルデータベースのエンジンを使用しています。この点は、次のセクションで詳しく説明します。

Force.com は、トランザクションエンジンのほかにも複数の永続化テクノロジーを備えており、さまざまな処理でスピードと拡張性を実現しています。たとえば、トランザクションエンジンとは分離された機能として提供されている検索エンジンは、全文検索と全文インデックス化を最適化して、アプリケーションの応答速度をさらに高めます。アプリケーションでデータが更新されると、検索サービスのバックグラウンドプロセスでは、テナント固有のインデックスやユーザ固有のインデックスをほぼリアルタイムで非同期的に更新します。トランザクションエンジンと検索サービスのタスクが分離されているため、アプリケーションでインデックスを更新する必要はなく、トランザクションを効率的に処理できます。また、ユーザに対しても正確な検索結果をすばやく提供できます。

以上、Force.com のメカニズムの基盤を成す主要なアーキテクチャコンポーネントの概要を説明しました。続いては、Force.com のトランザクションエンジンを支えるデータモデルの構成要素を取り上げ、その構造や役割を解説します。

マルチテナントのデータモデル

クラウドプラットフォームを使って、常に変化する大規模なデータベース構造をアプリケーションやテナントに代わって管理するというシナリオを考えてみましょう。もし、データベースで扱うのが実データだとしたら、サービスの拡大によって対応しきれなくなります。Force.com では、そのようなことにはなりません。以下の図に示すように、Force.com のストレージモデルでは、メタデータ、データ、ピボットテーブルを使用して、データベース構造を仮想的に管理します。

Fdc-mt-data-model.png

ユーザがアプリケーションスキーマを作成すると、UDD によって、オブジェクトのほか、項目、リレーションなどのオブジェクト属性に関するメタデータが取得されます。同時に、一連の仮想テーブルで使われる構造化データ、非構造化データが、少数の巨大なデータベーステーブルに格納されます。また、関連性のあるマルチテナントインデックスの集合が、正規化されていないデータを含んだシンプルなピボットテーブルとして実装され、組み合わされたデータセットの機能性が向上します。この後のセクションでは、それぞれのコンポーネントについて順に説明していきます。

メタデータ

Force.com では、MT_Objects と MT_Fields という 2 つのコアとなる内部テーブルを使用して、テナントのスキーマオブジェクトに対応するメタデータを管理します (便宜上、一部のテーブル名や列名では、Force.com 上での実際の呼称とは異なる表現を使用しています)。

  • MT_Objects には、組織がアプリケーションで定義したオブジェクト (テーブル) に関するメタデータが格納されます。例としては、オブジェクトの一意の ID (ObjID)、オブジェクトを所有する組織の一意の ID (OrgID)、オブジェクトの名前 (ObjName) などがあります。
  • MT_Fields には、組織が個々のオブジェクトで定義した列 (項目) に関するメタデータが格納されます。例としては、項目の一意の ID (FieldID)、項目が属するオブジェクトを所有する組織の ID (OrgID)、項目が属するオブジェクトの ID (ObjID)、項目の名前 (FieldName)、項目のデータ型、項目に対するインデックス化の必要の有無を示すブール値 (IsIndexed)、オブジェクト内のほかの項目との位置関係 (FieldNum) などがあります。

データ

MT_Data には、アプリケーションでアクセス可能なデータが格納されます。このデータは、MT_Objects と MT_Fields のメタデータの定義にもとづいて、各組織のオブジェクトや項目に対応付けられます。MT_Data テーブルの各行には、データを識別するための複数の列があり、グローバルに一意な識別子 (GUID)、行を所有する組織の ID (OrgID)、行が属するオブジェクトの ID (ObjID) などが格納されます。そのほかには、レコードに対応した「自然な」名前が格納される列もあります (たとえば、取引先レコードの場合は企業名、ケースレコードの場合は問い合わせ番号など)。

MT_Objects と MT_Fields で定義したオブジェクトと項目に対応するアプリケーションデータは、MT_Data テーブルの可変列 (スロットと呼ばれることもあります) に格納されます (次の図の Value0 ~)。可変列では、アプリケーションのあらゆる構造化データ (文字列、数字、日付など) を格納できるように、可変長の string データ型を使用します。なお、同じオブジェクトの複数の項目を MT_Data 内の同一のスロットに対応付けることはできません。同一のスロットで複数の項目の情報を管理できるのは、各項目がそれぞれ異なるオブジェクトに属している場合に限られます。

Fdc-mt-flex-columns.png

MT_Fields は、標準的な構造化データ (テキスト、数字、日付、日付/時間など) のほか、特定の用途で使用される「リッチな」構造化データもサポートします。たとえば、選択リスト (列挙型の項目)、自動採番 (数値を繰り上げて自動的に連番を設定する項目)、数式 (ほかの項目の値を使って自動的に値を生成する参照のみの項目)、主従関係 (外部キー)、チェックボックス (ブール値)、メール、URL などのデータ型に対応しています。また、Null 値を禁止する必須項目を指定したり、カスタムの入力規則 (例: ある項目で、ほかの項目よりも大きな値を入力しない場合にレコードを保存できないようにする) を設定したりすることも可能です。こうした処理は Force.com により実行されます。

組織でオブジェクトが作成されたり変更されたりした場合、Force.com では、そのオブジェクトを定義する MT_Objects テーブルでメタデータの行を操作します。項目についても同様で、Force.com では、MT_Fields 内のメタデータの行を操作します。これにより、その項目の情報が、MT_Data 内の特定の可変列に反映されます。Force.com では、オブジェクトや項目の定義を、実際のデータベース構造としてではなくメタデータとして管理しているため、マルチテナント型オンラインアプリケーションスキーマのメンテナンスというアクティビティを、テナントやユーザのアクティビティを中断することなく行えるようになっています。一方、従来型のリレーショナルデータベースシステムはどうかというと、オンラインでテーブルの再定義を実行する場合、プロセスは複雑で手間のかかるものとなり、メンテナンス期間を設けてその間稼働を停止する必要が生じます。

上の図は MT_Data の概要を示したものですが、可変列が汎用データ型 (可変長 string 型) であるため、文字、数字、日付といったさまざまなデータ型を持つ構造化データを 1 つの列に格納することができます。

Force.com ではすべての可変列のデータを標準的な形式で格納し、アプリケーションによるデータの読み書き時には、基盤となるデータベースシステムのデータ型変換機能 (TO_NUMBER、TO_DATE、TO_CHAR など) を必要に応じて利用します。

MT_Data には、上の図に示した列以外にもさまざまな列があります。たとえば、データの監査に使える 4 つの列が用意されており、レコードを作成したユーザ、レコードが作成された日時、レコードを最後に変更したユーザ、レコードが最後に変更された日時などの情報が格納されます。また、IsDeleted という列もあり、レコードが削除された日時が自動的に格納されます。

Force.com では、項目を CLOB (Character Large OBjects) として宣言すると、最大で 32,000 字のテキストを格納できるようになります。MT_Data 内の CLOB 型の行では、行に収まりきらないデータを MT_Clobs というテーブルに格納し、必要に応じて MT_Data と MT_Clobs のデータを結合する処理を行います。

注: CLOB は検索スピードを向上させる目的でも使われ、データベース外にインデックス化された形で格納されます。詳細は、Force.com のテキスト検索エンジンに関する後続のセクションを参照してください。

インデックス

Force.com では、さまざまなタイプの項目に自動的にインデックスを付けることによって拡張性を実現しています。ユーザがインデックス作成のことを気に病む必要はありません。このセクションでは、マルチテナントでのインデックスデータ管理における Force.com 独自の手法について詳しく説明します。

従来型のデータベースシステムでは、データベーステーブルから特定の条件に一致する項目を持つ行をすばやく検索する手段として、ネイティブのデータベースインデックスを使用します。しかし、Force.com の場合、MT_Data の可変列に対してネイティブのデータベースインデックスを作成するのは合理的なやり方とは言えません。1 つの可変列には、データ型が異なる複数の項目のデータが格納されるためです。そこで、Force.com では、インデックス化を行う項目のデータを MT_Indexes というピボットテーブルの適切な列に同期的にコピーすることで、MT_Data のインデックスを管理しています。

MT_Indexes テーブルは、StringValue (文字列)、NumValue (数字)、DateValue (日付) をはじめとする、強く型付けされたインデックス付きの列を格納し、Force.com ではこれらを使用して対応するデータ型を持つ項目を検索します。たとえば、MT_Data テーブルの可変列にある文字列型の値、日付型の値は、MT_Indexes テーブルの StringValue、DateValue にそれぞれコピーされます。MT_Indexes テーブルのインデックスは、一意ではない標準的なデータベースインデックスです。構造化データを含む項目を参照する検索パラメータが内部的なシステムクエリの中に含まれている場合、Force.com のカスタムクエリオプティマイザでは MT_Indexes テーブルを使って関連するデータアクセス処理を最適化します。

注: Force.com では複数の言語を対象にした検索が可能です。これは、システムが大文字・小文字処理のアルゴリズムを使用して、文字列型の値を大文字と小文字を区別しない汎用形式に変換しているためです。MT_Indexes テーブルの StringValue 列は、この形式の値を格納します。実行時には、クエリオプティマイザが自動的にデータアクセスの処理を定義し、最適化された SQL ステートメントによって、検索要求で指定された文字に一致する変換済みの StringValue を取得します。

Force.com では、値が一意であることを必須とするオブジェクトの項目を組織が指定できます (大文字と小文字を区別するかどうかも指定可能)。こうしたオブジェクトに一意のデータベースインデックスを作成することは、MT_Data の構成、項目のデータの Value 列が共有されることなどを考慮すると、合理的なやり方とはいえません (先ほど、一意でないインデックスに関するセクションで説明した状況と同様です)。

Force.com では、カスタム項目の一意性を確保するために MT_Unique_Indexes というピボットテーブルを使います。このテーブルは MT_Indexes テーブルに非常によく似ていますが、「ネイティブのデータベースインデックスが一意でなければならない」という点が異なります。アプリケーションで一意の値のみを格納する項目に一意でない値を挿入しようとしたり、一意でない値を含む既存項目を、一意の値しか格納しない設定にシステム管理者が変更したりしようとすると、Force.com ではエラーメッセージを表示します。

ごくまれに、Force.com の外部検索エンジン (後述) が過負荷などの理由で使用できなくなり、検索要求にタイムリーに応答しなくなる場合があります。このような状況が発生すると、Force.com では検索を要求したユーザにエラーを返すのではなく、二次的な代替の検索メカニズムで検索を実行します。

Force.com に実装されているのは、データベースを直接クエリするフォールバック検索というメカニズムです。ここでは、検索対象となるレコードの Name 項目が検索条件になります。Force.com では、すべてのレコードの Name 項目を記録する MT_Fallback_Indexes というピボットテーブルを使うことで、過負荷につながるユニオンクエリを実行せずに、複数のテーブルにまたがるグローバルなオブジェクト検索を最適化します。MT_Fallback_Indexes の更新はトランザクションによるレコードの変更と同期して行われるため、検索時には常に最新のデータベースにアクセスできます。

MT_Name_Denorm テーブルは、MT_Data の各レコードの ObjID 項目と Name 項目を格納する、シンプルなデータテーブルです。あるアプリケーションで、親子関係のリレーションが設定されているレコードの一覧を提供する必要がある場合、Force.com ではこのテーブルを使って比較的単純なクエリを実行し、参照先レコードの Name 項目を取得して、アプリケーションのハイパーリンクの一部として表示します。

リレーション

Force.com では、「参照関係」(Lookup Relationship) というデータ型を提供しており、組織ではこれを使ってテーブル間のリレーション (参照の整合性) を宣言できます。組織がオブジェクトの項目を参照関係型として宣言すると、Force.com ではその項目を MT_Data テーブルの Value 列に対応付け、関連付けられたオブジェクトの ObjID をそこに格納します。

リレーションの結合処理を最適化するために使われるのは、MT_Relationships というピボットテーブルです。このシステムテーブルには基盤となるデータベースに固有の複合インデックスが 2 種類用意されており、必要に応じてオブジェクトの検索を双方向に、効率的に実行できます。

項目履歴

Force.com では、わずかなマウス操作で項目の変更履歴を記録できるようになります。テナントで特定の項目に対する変更履歴の追跡が有効になると、システムでは内部のピボットテーブルを使って、該当項目の変更情報 (新旧の値、変更日など) を非同期的に記録します。

メタデータ、データ、インデックスデータのパーティショニング

Force.com では、データ、メタデータ、ピボットテーブルのあらゆる構造 (その基盤となるデータベースインデックスも含む) は、ネイティブのデータベースのパーティショニングメカニズムによって、テナント別の組織 ID (OrgID) ごとに物理的に分離されています。パーティショニングとは、大規模な論理データ構造を管理しやすい単位に物理的に分割するデータベースの技術です。これは、マルチテナント環境のような大規模データベースシステムのパフォーマンス、拡張性、稼働率の向上を図るうえで有効です。Force.com のすべてのクエリでは、ターゲットとしてテナントの特定の情報を指定しますが、その際にクエリオプティマイザのアクセス先を該当のテナントのデータを含んだパーティションのみに限定することで、テーブルやインデックス全体を参照する必要がなくなります。この最適化の手法は「パーティションプルーニング」とも呼ばれます。

マルチテナントのアプリケーション開発

前のセクションでは、Force.com がメタデータとデータの格納に使用しているアーキテクチャについて説明しました。このセクションでは、スキーマの基盤となるメタデータを作成し、データを管理するアプリケーションを開発するための方法を簡単に説明します。

ブラウザベースの開発環境

Force.com では、ブラウザベースの開発環境を使用して、サーバサイドのアプリケーションコンポーネントを宣言的に開発できます。この開発環境は、通常「設定画面」と呼ばれます。この設定画面は、アプリケーションスキーマ構築プロセスのあらゆる側面をサポートしており、アプリケーションのデータモデル (オブジェクト、項目、リレーションなど)、セキュリティと共有のモデル (ユーザ、プロファイル、ロール階層など)、ユーザインターフェース (ページレイアウト、データ入力フォーム、レポートなど)、宣言型ロジック (ワークフロー)、プログラムロジック (ストアドプロシージャ、トリガ) などを、マウス操作で定義できるようになっています。たとえば、次のスクリーンショットは Force.com のスキーマビルダーの画面を示していますが、このツールを使うと、ER 図を作成するときのような直観的な操作でデータモデリングを行えます。

Fdc-mt-schema-builder.png

設定画面を使うと、システムに組み込まれたさまざまな機能を利用して、標準的なアプリケーション機能を簡単に実装できます。従来のデータベースシステムのように複雑でエラーを招きやすいコーディングを行う必要はありません。

たとえば、次のような機能があります。

  • Force.com ネイティブのユーザインターフェース: ユーザインターフェースをコーディングなしで容易に開発できます。クエリ、挿入、更新、削除など、データアクセスに関する標準的な処理は、ユーザインターフェースのバックグラウンドで実行されます。ネイティブのプラットフォームで実行する個々のデータ操作では 1 度に 1 オブジェクトを変更でき、変更内容は独立したトランザクションとして自動的にコミットされます。
  • ワークフロー: ワークフローは宣言型のトリガであり、事前に定義しておいたアクションを、挿入や更新などの処理にもとづいて実行します。これにより、項目の更新やメッセージの送信なども実行できます。トリガのタイミングについては、ワークフロールールで条件を指定します。たとえば、「レコードが更新された場合に [状況] 項目の値をただちに「更新済み」に変更する」といったワークフローを宣言することなどが可能です。ワークフローに関するすべての処理は、ワークフローをトリガするトランザクションのコンテキストの範囲で行われます。システムがトランザクションをロールバックすると、そこに関連付けられたワークフローの実行済みの処理もすべてロールバックされます。
  • セキュリティ: オブジェクトで機密データを格納するテキスト項目を定義する場合、Force.com では該当するデータの暗号化を簡単に設定できます。また、入力時にマスキングを適用して画面の覗き見を防止するオプションも提供されています。項目の暗号化には 128 ビットキーの AES (Advanced Encryption Standard) アルゴリズムが使用されます。
  • 宣言型の入力規則: 入力規則を使用すると、ドメインのデータの整合性を確保するためのルールを、プログラミングの手間なく容易に適用できます。たとえば、「LineItem (商談品目) オブジェクトの Quantity (数量) 項目に常に 0 よりも大きい値が入力されるようにしたい」といったニーズがある場合などに役立ちます。
  • 数式項目: 計算式を設定した項目をオブジェクトに簡単に追加できる宣言型の機能です。たとえば、LineItem (商談品目) オブジェクト内に LineTotal (品目合計) の値を算出する項目を追加することなどが可能です。
  • 積み上げ集計項目: オブジェクトをまたがる項目間で、子となる項目の情報を親となる項目で集計できる機能です。たとえば、SalesOrder (発注) オブジェクト上に OrderTotal (発注合計) という項目を作成し、LineItem (商談品目) オブジェクトの LineTotal (品目合計) 項目の値を積み上げ集計するような設定が可能です。

注: 内部的には、数式項目と積み上げ集計項目ではネイティブのデータベース機能が使われており、値の再計算は処理中のトランザクションの一部として効率よく同期的に実行されます。

API

Force.com では、オープンで標準に準拠した API を使ってアプリケーションを開発できます。RESTful APISOAP ベースの Web サービス API という 2 種類の API が提供されており、Force.com のさまざまな機能を利用できます。これらの API により、次のようなことが可能になります。

  • アプリケーションスキーマを記述するメタデータを操作
  • ビジネスデータの作成、参照、更新、削除 (CRUD) を実行
  • 大量のレコードを非同期で一括ロード
  • 安全かつ拡張性のある方法で、ほぼリアルタイムにデータストリームを公開
  • 最小限の手間でソーシャルネットワーキング機能をアプリケーションに組み込む
  • プッシュ型の通知、データフィードなどのソーシャルコラボレーション機能をあらゆるアプリケーションに追加

各 API の詳細は、Developer Force で、インテグレーションに関する記事を参照してください。

クエリ言語

Force.com では、Salesforce Object Query Language (SOQL) を使用して、シンプルでありながら非常に強力なデータベースクエリを作成できます。SOQL では、SQL (Structured Query Language) の SELECT に似たコマンドを使用して、ソースオブジェクト、取得対象の項目のリスト、ソースオブジェクト内の行の選択条件を指定できます。たとえば、次に示す SOQL クエリは、「Acme」という文字列に一致する Name 項目を持つ Account レコードから、ID 項目と Name 項目の値を返します。

SELECT Id, Name FROM Account WHERE Name = 'Acme'

Force.com は、多言語をサポートする全文検索エンジンを備えており、あらゆるテキスト系の項目に対して自動的にインデックスを作成します。Force.com で開発したアプリケーションには、この検索エンジンがデフォルトで統合され、SOSL (Salesforce Object Search Language) というクエリ言語によってテキスト検索を実行できます。1 回で 1 つのオブジェクトのみをクエリする SOQL とは異なり、SOSL では、テキスト、メール、電話などの情報を、複数のオブジェクトで同時に検索できます。たとえば、次に示す SOSL は、Lead オブジェクトと Contact オブジェクトを対象に、「Joe Smith」という文字列を含む Name 項目を検索し、条件に一致するレコードから名前と電話の情報を返します。

FIND {"Joe Smith"} IN Name Fields RETURNING lead(name, phone), contact(name, phone)

Apex と手続き型のロジック

Apex は、Java に非常によく似た、強力な開発言語です。Apex によって、アプリケーションスキーマ内で手続き型のロジックを一元的に処理することが可能になります。Apex コードでは、プログラムの変数や定数の宣言のほか、Force.com で標準的に使うフロー制御ステートメント (if-else、loop など)、データ操作 (insert、update、upsert、delete)、トランザクション操作 (setSavepoint、rollback) の実行が可能です。

Apex で記述したプログラムは 2 つの形式で Force.com に格納できます。1 つ目は、メソッドを持つ名前付きの Apex クラス (従来のデータベースにおけるストアドプロシージャに相当) であり、これはアプリケーションが必要に応じて実行できます。2 つ目はデータベーストリガであり、これは特定のデータベース処理イベントの前後に、自動的に実行されます。Force.com では、いずれの場合も、Apex コードをコンパイルし、メタデータとして UDD に格納します。Apex プログラムが組織で初めて実行されると、Force.com のランタイムインタプリタによってコンパイル済みのプログラムが MRU キャッシュにロードされます。それ以降は、同じ組織内のユーザが同じルーチンを使う場合にはメモリ上のコンパイル済みプログラムを共有できるため、メモリ消費が抑制され、再コンパイルによるオーバーヘッドを回避できます。

Apex では、シンプルなキーワードを要所要所に追加するだけで、アプリケーションに固有のさまざまなニーズに対応できるようになります。たとえば、メソッドをカスタムの RESTful API コールや SOAP ベースの API コールの形で公開する、非同期でスケジューリングを行う、大量の操作をバッチ処理するといったことが可能になります。

Apex は、新しいタイプの手続き型言語であると同時に、信頼性の高いマルチテナント環境を実現するための重要な Force.com コンポーネントでもあります。Force.com では、実行時のコードエラーを防止するため、Force.com のクラスに組み込まれているすべての SOQL ステートメントと SOSL ステートメントを自動的に検証します。その後、有効なクラスに関連付けられたオブジェクトの依存関係にかかわる情報を取得し、依存関係のあるコードを壊す可能性のある変更がメタデータに対して行われることを防ぎます。

Apex では、標準クラスとシステムの静的メソッドの多くで、主要なシステム機能に対するインターフェースを提供しています。たとえば、insert、update、delete などのシステムの静的な DML メソッドにはシンプルなブール値パラメータがあり、開発者は実行する一括処理のオプション (逐次保存モードもしくは一括保存モード) を指定できます。さらに、これらのメソッドは、処理が失敗したレコードとその理由をコール元のルーチンで特定するための結果オブジェクトも返します。Apex は、このほかにもさまざまな形で Force.com の機能と緊密に連携しています。組み込みのメールクラス、XmlStream クラスなど、例を挙げれば切りがありません。

マルチテナントのプロセス

Force.com では、ほとんどの領域で、すぐれたパフォーマンスと拡張性が実現されています。その理由は、サービスを開発するセールスフォース・ドットコムのエンジニアたちに、以下の 2 つの原則が徹底されているためです。

  • あらゆる物事を可能な限り効率化する
  • 開発者があらゆる物事を可能な限り効率化できるよう支援を行う

この後のセクションでは、上記の原則を踏まえながら、Force.com 独自のプロセスについて説明します。

クエリ

現在、ほとんどのデータベースシステムでは、ターゲットとなるテーブルやインデックスのデータに関する統計をもとにクエリ実行プランを最適化する、コストベースのオプティマイザを採用しています。しかし、通常こうしたオプティマイザはシングルテナントアプリケーションを想定した設計になっており、マルチテナント環境でクエリを実行する場合のデータアクセス方式には対応していません。たとえば、マルチテナント環境で、大量のデータを持つオブジェクトをターゲットとするクエリを実行する場合には、より広範なアクセス権を持つユーザ (例: すべてのレコードを参照できるマネージャ) と、より限定的なアクセス権を持つユーザ (例: 自分の業務に関係するレコードしか参照できない営業担当者) に対して、それぞれ異なる実行プランを適用したほうが効率的です。

Force.com では、マルチテナントシステムに最適なクエリ実行プランを決定するうえで必要な統計情報を提供するために、各仮想マルチテナントオブジェクトのオプティマイザ用の統計情報 (テナントレベル、グループレベル、ユーザレベル) を完全な状態で保持しています。統計情報には、特定のクエリがアクセスする可能性のある行の数が反映されます。テナント固有のオブジェクトに関する基本情報 (例: テナントが所有する行の総数) だけでなく、詳細情報 (例: 特定の権限を割り当てられたグループやエンドユーザがアクセスする可能性がある行の数) も検討の対象になります。

Force.com では、以上のほかにも、特定のクエリに役立つ、さまざまなタイプの統計情報を保持しています。たとえば、すべてのカスタムインデックスでは、関連項目に含まれる Null ではない一意の値の総数を把握する統計情報を利用できます。また、選択リスト項目では、個々のリストの値のカーディナリティ (取り得る値の種類の絶対数) を示すヒストグラム (度数分布図) を利用できます。

既存の統計情報が利用できなかったり、役に立たないとみなされたりした場合、Force.com のオプティマイザでは、いくつかの戦略を利用して、状況に適したクエリを作成します。たとえば、オブジェクトの Name 項目で絞り込みを行うクエリでは、MT_Fallback_Indexes テーブルを使って、要求された行を効率的に検索できます。また、不足している統計情報を実行時にオプティマイザによって動的に生成することもできます。

Force.com のオプティマイザでは、こうした統計情報のほか、システムユーザのセキュリティ領域に関する情報を保持する内部的なセキュリティ関連テーブル (Groups、Members、GroupBlowout、CustomShare) から、ユーザのグループメンバーシップ、オブジェクトや項目に対するカスタムアクセス権といった情報を取得します。これらの情報は、個々のユーザレベルでクエリの絞り込み条件の精度を決定する場合に非常に重要です。

次の図は、MT_Data などの巨大なヒープテーブル内に存在するデータを要求された場合の、Force.com による処理の流れを示しています。要求は、API コールやストアドプロシージャなどの、あらゆるソースから送られてきます。Force.com では最初に、マルチテナントを想定した統計情報を検討する「前処理クエリ」を実行します。その後、このクエリの結果に従って、特定の設定での実行用に最適化された、ベースとなるデータベースクエリを作成します。

Fdc-mt-query-flow.png

Force.com では、次の表のように、ユーザのアクセス権限とクエリの絞り込み条件の精度にもとづいて、同一のクエリを 4 種類の異なる方法で実行できるようになっています。

前処理のクエリにおける実行基準
作成されるデータベースアクセスクエリの内容
ユーザのアクセス権限
絞り込み条件の精度
ネストされたループ結合 - ユーザが参照権限を持つ行のビューを使用
絞り込み条件に関連付けられたインデックスを使用
順序を指定したハッシュ結合 - MT_DATA を使用
絞り込み条件に関連付けられたインデックスを使用

検索

Web ベースアプリケーションの検索機能に対するユーザの要望は年々高まっており、すべての範囲または指定した範囲を対象とするアプリケーションデータベースの検索で、ランク付けされた最新の結果が 1 秒以内に返されることが期待されています。Force.com では、そうした要望に応える強力な検索機能をアプリケーションで実現するために、トランザクションエンジンとは分離された形で検索エンジンを使用しています。2 つのエンジンの関係は次の図のようになります。検索エンジンは、トランザクションエンジンからデータを受け取り、それを使って検索インデックスを作成します。トランザクションエンジンは、検索要求を検索エンジンに転送し、検索エンジンから検索結果を受け取ります。トランザクションエンジンではその結果を利用して、検索要求を満たす行を特定します。

Fdc-mt-search-flow.png

アプリケーションでテキスト系の項目 (CLOB 型の項目、Name 項目など) のデータが更新された場合、バックグラウンドプロセスのプール (インデックスサーバ) で、対応するインデックスが非同期的に更新されます。このインデックスは、コアのトランザクションエンジンの外側で検索エンジンによって管理されます。Force.com では、インデックスの作成処理を最適化するため、トランザクションのコミット時に専用の内部テーブル (インデックス化が必要なデータを格納するテーブル) に一連の変更データを同期的にコピーします。これによりデータソースが小さくなり、インデックスサーバがディスクから読み取る必要のあるデータ量が最小化されます。検索エンジンでは、インデックスを組織 (テナント) 別に管理しています。

インデックスサーバの負荷や稼働率によっては、インデックスの更新が実際のトランザクションに対して遅延することがあります。Force.com では、このような状況下で無効なインデックスによって予期しない検索結果が返されることを防ぐため、最近更新された行の MRU キャッシュ (Most Recently Used cache: 最近使用したキャッシュ) を用意して、全文検索結果を生成する際に利用しています。この MRU キャッシュはユーザ単位および組織単位で管理されているため、検索範囲を効率的に制御することが可能です。

Force.com の検索エンジンでは、複数の方法を使って検索結果のレコードのランク付けを最適化します。たとえば、検索を行うユーザのセキュリティ領域にもとづいてそのユーザがアクセス権を持つ行のランクを上げたり、行の変更履歴にもとづいて更新頻度の高い行のランクを上げたりすることなどが可能です。ユーザは、ニーズに応じて検索結果の表示順を指定できます。たとえば、更新日時の新しい行を優先的に表示することなどができます。

一括処理

トランザクションが集中するアプリケーションでは、反復処理を一括実行することで、オーバーヘッドを縮小して、パフォーマンスを大幅に向上させることができます。たとえば、アプリケーションが大量の新しい行をロードする場合の処理について考えてみましょう。ループを使って行を 1 つずつ挿入するルーチンを使用すると、挿入処理ごとに API コールが発生するため効率が低下します。行の配列を作成して、1 回の API コールですべてを挿入するルーチンを使用したほうがはるかに効率的です。

Force.com の一括処理は API コールに組み込まれているため、シンプルな手順で使用できます。明示的なステップだけでなく、それに関連付けられたすべての内部的なステップも一括処理されます。

Force.com の一括処理エンジンは、処理の各ステップで発生する個々のエラーに自動的に対処します。一括処理が逐次保存モードで始まると、エンジンでは既知の開始状態を識別して、プロセスの各ステップ (項目データの一括検証、前処理のトリガの一括実行、レコードの一括保存など) を実行します。ステップでエラーが検出されると、エラーが含まれる処理とそれに関連した処理をロールバックし、エラーの原因となった行を除外後、残りの行に対する一括処理を続行します。連続する各フェーズで行のサブセットがエラーを起こさずにコミットされるまで、この操作を繰り返します。アプリケーションでは、返されたオブジェクトを検証して、エラーが発生した行とエラーの内容を特定できます。

注: 必要に応じて、一括保存モード (エラーを 1 件でも検出すると処理を中止する保存モード) を設定することも可能です。一括処理時のトリガの実行は、処理量を制限する内部ガバナの影響を受けます。

スキーマの変更

オブジェクトの定義を変更する場合、UDD のメタデータの更新に加えて、複雑な処理が必要になることがあります。このような場合、Force.com では効率的なメカニズムを使って、クラウドデータベースサービスのパフォーマンスに及ぼされる総合的な影響を軽減します。

例として、列のデータ型を選択リストからテキストに変更したときに、バックグラウンドで行われる処理について考えてみましょう。Force.com ではまず列のデータ用に新しいスロットを割り当て、現在の値に関連付けられている選択リストのラベルを一括コピーします。続いて、新しいスロットをポイントするように、列のメタデータを更新します。こうした処理が実行されている間も、ユーザは通常通りデータにアクセスすることができます。アプリケーションの利用に支障が生じることはありません。

もう 1 つ、オブジェクトに積み上げ集計項目を追加するケースについても考えてみましょう。この場合、Force.com では効率的に一括処理を実行し、バッググラウンドで非同期的に初期集計を行います。この集計処理中にユーザが新しい項目を表示しようとすると、Force.com は該当項目の値が計算中であることを示すメッセージを表示します。

分離と保護

マルチテナントシステムでは、共有リソースの独占を防止するための仕組みが必要です。こうした占有は悪意にもとづいた行為に起因するものばかりでなく、ユーザの不注意によって発生することもあります。Force.com では、Force.com コード (Apex) でさまざまなガバナ制限やリソース制限を使って、この問題に対処します。たとえば、コードスクリプトの実行を詳細に監視して、使用できる CPU 時間、消費できるメモリ容量のほか、実行できるクエリ、DML ステートメント、計算処理、アウトバウンド Web サービスコールなどの数を制限します。Force.com のオプティマイザでは、クエリがきわめて非効率的であると判断すると、呼び出し元にランタイム例外を返します。少々厳しく見えるかもしれませんが、さまざまなアプリケーションを実行するデータベースシステムの総合的な拡張性とパフォーマンスを維持するには、こうした制限は不可欠です。また、長期的に見ても、一連の制限は、開発者のコーディングスキルを高め、プラットフォームのあらゆるユーザに快適な環境を提供することにつながります。たとえば、膨大な数の行を 1 つずつ更新する非効率的なループ処理をコーディングすると、リソース制限によりランタイム例外が返されるため、開発者は Force.com が提供する効率的な一括処理の API コールを使うようになります。

セールスフォース・ドットコムでは、質の低いアプリケーションによってシステムに問題が発生することを防ぐため、運用環境への導入プロセスを厳格に管理しています。新しいアプリケーションを開発環境から運用環境に移行させるには、アプリケーションの Force.com コードのルーチンを検証する単体テストの実施が求められます。テストでは、アプリケーションのソースコードの 75% 以上をカバーする必要があります。セールスフォース・ドットコムでは、提出された単体テストを Force.com のサンドボックス環境で実行し、新しいアプリケーションコードが既存のマルチテナント環境のパフォーマンスと拡張性に及ぼす影響を総合的に確認します。個々の単体テストの結果には、実行した行の総数などの基本情報や、テストで実行されなかったコードに関する詳細情報が記録されます。

セールスフォース・ドットコムが運用環境への移行を承認した後のプロセスは、単一のトランザクションで構成されます。具体的には、まずアプリケーションのすべてのメタデータを Force.com の運用環境にコピーして所定の単体テストを再実行します。この過程で何らかのエラーが発生した場合には、Force.com はトランザクションをロールバックして、問題の解決を指示する例外メッセージを返します。

注: セールスフォース・ドットコムでは、Force.com のリリースがアップデートされる際には、必ずすべてのアプリケーションを対象に開発環境での単体テストを再実行し、システムの新機能や拡張機能が既存のアプリケーションに問題を引き起こさないことを確認しています。

Force.com では、運用環境に移行したアプリケーションが稼動すると、組み込みのパフォーマンスプロファイラで分析を実行し、システム管理者に結果をフィードバックします。分析のレポートには、開発者がアプリケーションの改善に活用できるクエリ、データ処理、サブルーチンの遅延などに関する情報が記録されます。また、システム管理者がアプリケーションのデバッグに利用できるランタイム例外に関する情報も記録されます。

削除、復元、ごみ箱

アプリケーションでオブジェクトのレコードが削除された場合、MT_Data 内の対応する行の IsDeleted 列に削除のマーキングが付加されます。この処理により、その行はプラットフォームのごみ箱に移動されます。ごみ箱に移動されてから 15 日が経過すると、行は MT_Data から完全に削除されます。15 日以内であれば行を復元することが可能です。なお、ごみ箱に格納できるレコード数の上限は、各組織のストレージ容量に応じて異なります。

主従関係が設定されたレコードでは、親レコードの削除操作が実行されると、参照整合性に関する規則に違反する場合を除き、その親レコードに関連付けられたすべての子レコードは自動的に削除されます。たとえば、SalesOrder (発注) レコードと LineItems (商談品目) レコードの間に主従関係が設定されている場合、SalesOrder (発注) レコードが削除されると、LineItems (商談品目) レコードに対しても削除操作が自動的に適用されます。同様に、削除後にごみ箱から親レコードを復元した場合には、すべての子レコードが自動的に復元されます。

一方、参照関係が設定されたレコードでは、親レコードの削除操作が実行されると、すべての子レコードで参照関係の設定が自動的に Null に変更されます。削除後に親レコードを復元すると、Null に変更されていた参照関係が自動的に復元されます。ただし、削除後に新たに割り当てられたリレーションがある場合には、この復元は行われません。

削除したレコードはデータとともにごみ箱に移動され、組織がごみ箱からの削除を実行しない場合は、移動後 45 日を経過した時点で完全に削除されます。ごみ箱に格納されている間であれば、必要に応じてレコードとすべてのデータを復元できます。

統計から見る Force.com の実績

Force.com は実績を積み重ねながら、非常に高速で拡張性に富み、かつ信頼性の高いクラウドデータベースサービスへと成長を遂げてきました。インターネットスケールのアプリケーションをサポートする Force.com のすぐれた性能を示す一例として、下のグラフをご覧ください。この数年の変化を見ると、平均トランザクション件数 (拡張性の指標) が増加を続けているのに対し、平均ページ応答時間 (パフォーマンスの指標) は短くなっているか、そのままの水準を維持しています。

Fdc-mt-historical-stats.png

Force.com では、システムのパフォーマンスとセキュリティに関するリアルタイムの情報を trust.salesforce.com で公開しています。このサイトから、メンテナンスの予定、トランザクション件数や応答時間の実績などのシステム情報を確認できます。

まとめ

クラウドベースのサービスは、今もっとも注目を集めている IT リソースモデルです。厳しいグローバル経済下で、市場投入までの期間の短縮、設備投資の削減、競争力の強化が求められる中、多くの企業がクラウドベースのサービスへの移行を進めています。クラウドアプリケーション開発プラットフォームのようなサービスでは、企業は管理されたソフトウェアに必要に応じてすばやくアクセスできます。自社でデータセンターを運用する必要もなく、ハードウェアやソフトウェアの購入、インストール、設定、継続的な保守コストや管理の手間も発生しません。

Force.com は、Sales Cloud や Service Cloud をはじめとする Salesforce アプリケーションの基盤として、その大きな成功を背後から支えてきました。また、企業やサービスプロバイダがアプリケーションを開発してユーザに提供するためのプラットフォームとしての実績も上げています。サプライチェーン管理、請求処理、財務管理、コンプライアンス管理、人事管理、支払処理といったあらゆる種類のビジネスアプリケーションが Force.com で開発されています。「マルチテナントでメタデータ駆動型」という Force.com 独自のアーキテクチャは、クラウドに特化した設計になっており、セールスフォース・ドットコムが創業した 1999 年以来、ミッションクリティカルなインターネットスケールのアプリケーションを高い信頼性と安全性でサポートしています。開発者は、標準ベースの Web サービス API やネイティブの開発ツールを使って、アプリケーションのデータモデル (オブジェクト、リレーションなど)、ビジネスロジック (ワークフロー、入力規則など)、他のアプリケーションとのインテグレーションといった、Web ベースアプリケーションのあらゆるコンポーネントを簡単に構築できます。

セールスフォース・ドットコムのエンジニアたちがマルチテナント向けの最適化に継続的に取り組んできた結果、現在 Force.com では 1 日に 10 億件を超える複雑なビジネストランザクションを処理できるようになり、インターネットにおける空前の拡張性を実現しています。一括データ処理用の API、Apex、トランザクションエンジンと分離された全文検索エンジン、すぐれたクエリオプティマイザをはじめとするシステムの中核機能は、Force.com を利用するアプリケーションの効率と拡張性を大きく高めると同時に、開発者の負荷を大幅に軽減しています。

セールスフォース・ドットコムは、Force.com を利用するアプリケーションの運用環境への導入プロセスを厳格に管理し、あらゆるアプリケーションで世界最高レベルのパフォーマンス、拡張性、信頼性を実現しています。アプリケーションの導入後は、運用状況を継続的に監視して情報収集に努め、それらの情報を通して改善を積み重ね、新しいシステム機能の開発に生かしています。既存のアプリケーションや新しいアプリケーションでは、こうした取り組みの成果をダイレクトに享受できます。

関連リソース