---
schema_version: "1"
id: cb283147cebf1a05071156629ead5eca75fd1943787c8c3942824244f2d57ce9
title: 平台多租户架构
collection: architect
version: current
locale: zh-cn
portal_url: https://docs.salesforce.com/architect/current/zh-cn/fundamentals/guides/platform-multitenant-architecture.md
canonical_url: https://architect.salesforce.com/docs/architect/zh-cn/fundamentals/guide/platform-multitenant-architecture.html
source_site: architect.salesforce.com
content_type: documentation
content_hash: bd631c9d0f4c8a9b715b9a607e1b733db569fed0a0b14a3514c8a82b7136d352
products:
  - 基本知识
  - Architect Site Content Repo
updated_at: 2022-08-01T00:00:00Z
---
每天,[成千上万的企业和数百万用户](https://www.salesforce.com/customer-stories/)使用 Salesforce 平台支持的应用程序在云中运营他们的业务。平台为何如此成功？您为何可以Trust它来支持您的业务？该平台为像您这样的企业提供了哪些独特的好处？

此技术简介解释了 Salesforce 平台如何使用其独特的云计算软件架构提供可靠、可扩展和易于自定义的最终用户体验。阅读完此简介后，您将更好地理解使 Salesforce 平台成为业务应用程序令人信服的选择的基础技术。

# 平台概览

Salesforce 平台是成功云计算平台和相关应用程序生态系统的杰出示例。自千年之交以来,该平台一直是以下各项的有利基础:

- 适用于常见用例（例如销售和客户服务）的多个热门[业务应用](http://www.salesforce.com/products/)
- 适用于金融和医疗保健等更专业用例的[行业特定应用](https://www.salesforce.com/solutions/industries/)
- 适用于唯一用例的数百万个[自定义应用程序](https://www.salesforce.com/products/platform/overview/)

Salesforce 平台之所以如此成功和受欢迎,很大程度上是因为它独特的软件架构支持易于构建、使用、自定义和扩展的应用程序,具有卓越的[性能和可靠性](http://trust.salesforce.com/trust/)。平台软件架构的核心是多租户元数据驱动的设计。

<a href="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-platform.png" target="_blank">
    <image style="width:100%;border:1px solid #e5e5e5;margin-top:1rem;margin-bottom:1rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-platform.png" alt="Multitenant Platform">
</a>

Salesforce Platform 的软件架构是：

- _多租户_ — 隔离并同时支持许多_租户_（组织、业务部门等）的不同需求。
- _元数据驱动_ — 它允许每个租户使用_元数据_（描述用户界面 (UI) 和业务逻辑等元素的数据）轻松快速地自定义他们的应用程序和用户体验。

在您创建新应用程序对象或使用 Salesforce 平台编写一些代码时，平台不会在数据库中创建实际表或编译任何代码。相反，平台只是存储一些元数据，然后可在运行时用于动态实现虚拟应用程序组件。该平台确保每个租户的元数据都是专用的，并且易于更新，无需任何锁定或停机时间，以便每个租户都可以隔离地构建和自定义应用程序。Salesforce 平台使用相同的元数据提供自定义 API、_RESTful 和 Web_ 服务(基于 SOAP)界面，您可以使用这些界面将您的应用程序与其他应用程序和自动化流程集成在一起。

在[AppExchange](https://appexchange.salesforce.com/)这个平台广阔的应用程序市场中也有现成的解决办法。AppExchange 软件包由受信任的合作伙伴和独立软件供应商 (ISV) 组成的庞大生态系统构建而成,是来自第三方的元数据,描述了可用于满足特定业务需求的免费或付费应用程序扩展和整个应用程序。

为了支持这种高度可自定义和可扩展的架构，Salesforce Platform 的单个实例使用：

- 单个共享的_多租户数据库_，具有存储特定于租户的元数据和数据的单个模式。
- 一个_多租户内核_(应用程序运行时 ) , 读取元数据和数据,以在运行时为每个租户的用户提供特定于租户的应用程序、业务逻辑和 API。

这种将 Salesforce 受管内核与租户受管元数据明确分开的做法，使 Salesforce、租户和 ISV 能够在不受干扰的情况下独立发展其系统部分。

为构建此概述，本文的后续部分会提供有关平台独特功能的更多详细信息，这些功能源自其设计的关键方面，包括：

- 平台数据层
- 平台应用程序开发
- 内部平台处理
- 平台基础设施

## 平台数据层

Salesforce Platform 的应用程序运行时和创新数据层共同安全地隔离特定于租户的数据、模式自定义和业务逻辑。在高级别，模式支持各种用例：

- 在您创建或自定义应用程序时，平台会将相关元数据存储在共享数据库表中，该表为所有租户维护元数据。
- 当您使用应用程序读取或写入数据时，平台会将您的数据存储在为所有租户维护数据的共享数据库表中。
- 在后台，该平台还在内核用于优化运行时请求延迟的许多表中维护内部元数据。

但单个共享数据库和方案如何保持每个租户的数据私有？平台上的每个租户都被称为一个_组织_，或简称为_组织_。共享数据库表中每个特定于组织的记录都有一个 _OrgID_。当内核访问数据库时，它会使用此唯一标识符来确保每个组织的活动都是专用的。

<image style="width:100%;border:1px solid #e5e5e5;margin-top:1rem;margin-bottom:1rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-erd.png" alt="Multitenant Architecture ERD">

### 元数据

特定于组织的对象(传统关系数据库术语中的思想表 ) 、 字段、存储的过程、数据库触发器等都是元数据描述的虚拟结构,平台将这些元数据存储在一些称为_通用数据字典 (UDD)_ 的数据库表中。

- _MT_Objects_ 是存储有关您为应用程序定义的对象的元数据的数据库表，包括对象的唯一标识符 (ObjID)、贵组织 (OrgID) 和您为对象命名的名称 (ObjName)。
- _MT_Fields_ 系统表存储有关您为每个对象声明的字段（列）的元数据，包括字段的唯一标识符 (FieldID)、您的组织 (OrgID)、包含字段的对象 (ObjID)、字段的名称 (FieldName)、字段的数据类型、指示字段是否需要索引的布尔值 (IsIndexed)，以及字段在对象中相对于其他字段的位置 (FieldNum)。

因为元数据是一个关键组成部分，所以平台必须优化对元数据的访问；否则，频繁的元数据访问将阻止服务的扩展。考虑到这一潜在的瓶颈,该平台使用大量复杂的_元数据缓存_来维护内存中最近使用的元数据,避免影响性能的磁盘 I/O 和代码重新编译,并改进应用程序响应时间。

### 数据

根据 MT_Objects 和 MT_Fields 中的元数据定义，_MT_Data_ 系统表存储映射到所有特定于组织的表及其字段的应用程序可访问数据。每行包含标识字段，例如全局唯一标识符 (GUID)、拥有该行的组织 (OrgID) 和包含对象标识符 (ObjID)。MT_Data 表中的每一行都有一个名称字段，用于存储相应记录的“自然名称”；例如，客户记录可以使用“客户名称”，个案记录可以使用“个案编号”等等。

Value0 ... ValueN _弯曲列_也称为插槽，存储分别映射到 MT_Objects 和 MT_Fields 中声明的表和字段的应用程序数据。所有弯曲列都使用可变长度的字符串数据类型，以便它们可以存储任何结构类型的应用程序数据（字符串、数字、日期等）。如下图所示，同一对象的两个字段不能映射到 MT_Data 中的同一时段进行存储；但是，一个时段可以管理多个字段的信息，只要每个字段来自不同的对象。

<image style="width:100%;border:1px solid #e5e5e5;margin-top:1rem;margin-bottom:1rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-multitenant-data.png" alt="Multitenant Data">

MT_Fields 可以使用多种标准结构化数据类型中的任何一种，例如文本、数字、日期和日期/时间，以及特殊用途的*富结构化数据类型*，例如选项列表（枚举字段）、自动编号（自动递增、系统生成的序列号）、公式（只读派生值）、主-详细信息关系（外键）、复选框（布尔值）、电子邮件、URL 和其他。MT_Fields 也可以是必填项（不为空），并具有自定义验证规则（例如，一个字段必须大于另一个字段），这两个规则都由平台强制执行。

在您声明或修改对象时，平台会管理 MT_Objects 中定义对象的一行元数据。同样，对于每个字段，平台都会管理 MT_Fields 中的一行，其中包括将字段映射到 MT_Data 中特定弯曲列的元数据，用于存储相应的字段数据。因为平台将对象和字段定义作为元数据而不是实际的数据库结构来管理，所以系统可以容忍在线多租户应用程序模式维护活动，而不会阻止其他组织和用户的并发活动。相比之下，传统关系数据库系统的在线表重新定义通常需要临时锁定，并且通常需要费力、复杂的流程和计划的应用程序停机时间。

如上图中 MT_Data 的简化表示所示，弯曲列是通用数据类型（可变长度字符串），这使得平台能够在使用各种结构化数据类型（字符串、数字、日期等）的多个字段之间共享单个弯曲列。

该平台使用_规范格式_存储所有弯曲列数据，并在应用程序从弯曲列读取数据和将数据写入弯曲列时，根据需要使用基础数据库系统数据类型转换函数（例如 TO_NUMBER、TO_DATE、TO_CHAR）。

MT* 数据还包含上图中未显示的列。例如，有四个列来管理审计数据，包括哪个用户创建了行以及该行创建的时间，哪个用户上次修改了行以及该行上次修改的时间。MT_Data 还包含平台用来指示何时删除行的 \_IsDeleted* 列。

该平台还支持将字段声明为_字符大对象 (CLOB)_，允许存储最多 32,000 个字符的长文本字段。对于 MT *数据中具有 CLOB* 的每一行，平台将 CLOB 超出行存储在名为 \_MT_Clob 的表中，系统可以根据需要将其与 MT_Data 中的相应行连接。

**注意：**该平台还在数据库之外以索引的形式存储 CLOB，以便进行快速文本搜索。有关平台文本搜索引擎的更多信息，请参阅[搜索](/docs/architect/zh-cn/fundamentals/guide/platform-multitenant-architecture#搜索)。

### 索引

该平台会自动索引各种类型的字段，以提供可扩展的性能。

传统数据库系统依赖于本地数据库索引来快速查找数据库中具有匹配特定条件的字段的特定行。但是,为 MT* 数据的弯曲列创建本地数据库索引不切实际,因为平台使用单个弯曲列来存储具有不同结构数据类型的许多字段的数据。相反，平台通过将标记为索引的字段数据同步复制到 \_MT_Indexes* 数据透视表中的适当列来管理 MT_Data 的索引。

MT_Indexes 包含强类型的索引列，例如 StringValue、NumValue 和 DateValue，平台使用这些列来查找相应数据类型的字段数据。例如，平台会将 MT_Data 弯曲列中的字符串值复制到 MT_Indexes 中的 StringValue 字段，将日期值复制到 DateValue 字段，以此类推。MT_Indexe 的基础索引是标准的非唯一数据库索引。当内部系统查询包含引用对象中结构字段的搜索参数时，平台的自定义查询优化器使用 MT_Indexe 来帮助优化关联的数据访问操作。

_注意：_该平台可以处理多种语言的搜索，因为系统使用将字符串值转换为通用、不区分大小写的_大小写算法_。MT_Indexes 表的 StringValue 列以该格式存储字符串值。在运行时，查询优化器会自动构建数据访问操作，以便优化的 SQL 语句筛选相应的 case-folded StringValue，这反过来又对应于搜索请求中提供的文字。

该平台允许您指示对象中的字段何时必须包含唯一值（区分大小写或不区分大小写）。考虑到 MT_Data 的安排和字段数据的值列的共享使用，为对象创建唯一的数据库索引不切实际。（这种情况类似于上一节中讨论的非唯一索引。）

为了支持自定义字段的唯一性，该平台使用 MT_Unique_Indexes 数据透视表；该表与 MT_Indexes 表非常相似，只是 MT_Unique_Indexes 的基础本地数据库索引强制执行唯一性。当应用程序尝试将重复值插入需要唯一性的字段，或者管理员尝试对包含重复值的现有字段强制执行唯一性时，平台会向应用程序返回适当的错误消息。

在极少数情况下，平台的外部搜索引擎(在[搜索中](/docs/architect/zh-cn/fundamentals/guide/platform-multitenant-architecture#搜索)解释)可能会超载或不可用，并且可能无法及时响应搜索请求。平台不是向最终用户返回令人失望的错误，而是返回到次要搜索机制来提供合理的搜索结果。

_后备搜索_作为直接数据库查询实施，搜索条件引用目标记录的名称字段。为了优化全局对象搜索(跨越表的搜索)而无需执行潜在的昂贵联合查询,平台维护了一个记录所有记录名称的 _MT_Fallback_Indexes_ 数据透视表。当事务修改记录时，MT_Fallback_Indexe 的更新会同步发生，这样后备搜索始终可以访问最新的数据库信息。

_MT_Name_Denorm_ 表是一个精简数据表，它在 MT_Data 中存储每个记录的 ObjID 和名称。当应用程序需要提供父/子关系中涉及的记录列表时，平台使用 MT_Name_Denorm 表执行相对简单的查询，该查询检索每个引用记录的名称，以便在应用程序中显示，例如作为超链接的一部分。

### 关系

平台提供组织可用于声明表之间关系(引用完整性)的_关系_数据类型。当您使用关系类型声明对象的字段时，平台会将字段映射到 MT_Data 中的值字段，然后使用此字段存储相关对象的 ObjID。

为了优化连接操作，平台维护了一个 _MT_Relationships_ 数据透视表。此系统表有两个基础数据库唯一复合索引，可以根据需要在两个方向上高效遍历对象。

### 字段历史

只需单击几下鼠标，平台即可为任何字段提供历史跟踪。在组织启用特定字段的审计时，系统会异步记录有关字段更改的信息（旧值和新值、更改日期等），并使用内部数据透视表作为审计跟踪。

### 数据分区

所有平台数据、元数据和数据透视表结构，包括基础数据库索引，均由 OrgID 使用本地数据库分区机制进行物理分区。数据分区是数据库系统提供的成熟技术，用于将大型逻辑数据结构物理划分为更小、更易于管理的部分。分区还有助于提高大型数据库系统的性能、可扩展性和可用性，例如多租户环境。顾名思义，每个平台查询都针对特定组织的信息，因此查询优化器只需要考虑访问包含组织数据的数据分区，而不是整个表或索引。这种常见的优化有时被称为“分区修剪”。

## 平台应用程序开发

本节涵盖了应用程序开发人员如何创建模式的基础元数据，然后构建管理数据的应用程序。该元数据和数据存储在上一节描述的平台数据层中。

### 基于浏览器的无代码和低代码应用程序开发

开发人员可以使用平台的基于浏览器的开发环境(通常称为平台_设置_屏幕)来声明性地构建服务器端应用程序组件。设置的指点单击式 UI 支持应用程序模式构建过程的所有方面，例如创建应用程序的数据模型（包括对象及其字段以及关系）、安全和共享模型（包括用户、简档和角色层次结构）、用户界面（包括屏幕布局、数据输入表单和报表）、声明性逻辑（工作流）和程序逻辑（存储的程序和触发器）。例如，Salesforce Flow 可轻松自动化各种用例。如下所示，通过设置的 Flow Builder UI，您可以以图形方式设计和实施与用户交互的工作流，或者根据计划或由事件触发时自动启动。

<image style="width:100%;border:1px solid #e5e5e5;margin-top:1rem;margin-bottom:1rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-flow-builder.png" alt="Flow Builder">

设置屏幕使任何人都可以轻松开发和自定义应用程序，而无需（或只需很少）代码。例如：

- 平台原生 UI 无需任何代码即可轻松构建。本地应用程序 UI 在后台支持所有常见的数据访问操作，包括查询、插入、更新和删除。本地平台应用程序执行的每个数据操纵操作一次可以修改一个对象，并在单独的事务中自动提交每个更改。
- 当为包含敏感数据的对象定义文本字段时，您可以轻松配置字段，以便平台加密相应的数据，还可以选择使用输入掩码来隐藏屏幕信息。
- 声明性_验证规则_是组织无需任何编程即可强制执行域完整性规则的简单方法。例如，您可以声明验证规则，以确保 LineItem 对象的数量字段始终大于零。
- _公式字段_是平台的声明性功能，可轻松将计算字段添加到对象。例如，您可以向 LineItem 对象添加字段来计算 LineTotal 值。
- _累计汇总字段_是跨对象字段，可轻松在父对象中聚合子字段信息。例如，您可能会根据 LineItem 对象的 LineTotal 字段在 SalesOrder 对象中创建 OrderTotal 汇总字段。

**注意：**在内部，该平台使用本地数据库功能实施公式和累计汇总字段，并作为正在进行的事务的一部分高效地同步重新计算值。

### API

该平台提供了一些开发人员可以用来构建应用程序的开放[的基于标准](https://developer.salesforce.com/docs/apis)的 API。_RESTful 和 Web 服务_（基于 SOAP）API 都提供对平台许多功能的访问权限。使用这些不同的 API，应用程序可以：

- 操纵描述应用程序模式的元数据
- 创建、读取、更新和删除 (CRUD) 业务数据
- 异步批量加载或查询大量记录
- 以安全和可扩展的方式公开近乎实时的数据流

### 查询语言

应用程序可以使用 _Salesforce 对象查询语言 (SOQL)_ 构建简单但功能强大的数据库查询。与结构化查询语言 (SQL) 中的 SELECT 命令相似，SOQL 使您能够指定源对象、要检索的字段列表以及选择源对象中的行的条件。例如，对于名称等于字符串“Acme”的所有客户记录，以下 SOQL 查询会返回 ID 和名称字段的值。

`SELECT Id, Name FROM Account WHERE Name = 'Acme'`

该平台还包括一个全文、多语言搜索引擎，可以自动索引所有与文本相关的字段。通过使用 _Salesforce 对象搜索语言 (SOSL)_ 执行文本搜索，应用程序可以使用此预集成的搜索引擎。与一次只能查询一个对象的 SOQL 不同，SOSL 使您能够同时搜索多个对象的文本、电子邮件和电话字段。例如，以下 SOSL 语句会在“潜在客户”和“联系人”对象中搜索名称字段中包含字符串“Joe Smith”的记录，并从找到的每个记录中返回名称和电话号码字段。

`FIND {"Joe Smith"} IN Name Fields RETURNING lead(name, phone), contact(name, phone)`

### Apex 和 Pro-Code 应用程序开发

_Apex_在许多方面与Java相似,是一种强大的开发语言,开发人员可以使用它来集中其应用程序模式中的程序逻辑。Apex 代码可以声明程序变量和常量，执行传统的流控制语句（if-else、循环等），执行数据操纵操作（插入、更新、更新插入、删除），并执行事务控制操作（setSavepoint、回滚）。

您可以使用两种不同的形式将 Apex 程序存储在平台中:作为命名 Apex 类，其中包含应用程序在必要时执行的方法(类似于传统数据库术语中的已存储程序),或者作为在特定数据库操纵事件发生之前或之后自动执行的数据_库触发器_。无论哪种形式，平台都会编译 Apex 代码，并将其存储为 UDD 中的元数据。组织首次执行 Apex 程序时，平台的运行时解释器会将程序的编译版本加载到该组织的 MRU（最近使用）缓存中。此后，当来自相同组织的任何用户需要使用相同例程时，平台可以通过共享内存中已有的随时运行的程序来节省内存并避免重新编译程序的开销。

通过在此处添加一个简单的关键字，开发人员可以使用 Apex 来支持许多独特的应用程序要求。例如，开发人员可以将方法公开为自定义 RESTful 或基于 SOAP 的 API 调用，使其可异步计划，或将其配置为批量处理大型操作。

Apex 不仅仅是“另一种程序语言”。它是一个整体平台组件，帮助系统提供可靠的多租户。例如，平台会自动验证类中的所有嵌入 SOQL 和 SOSL 语句，以防止代码在运行时失败。然后，平台为有效类维护相应的对象依赖性信息，并将其用于防止更改元数据，否则元数据会破坏依赖代码。

许多标准 Apex 类和系统静态方法提供了基础系统功能的简单界面。例如，系统静态 DML 方法（例如插入、更新和删除）具有简单的布尔值参数，开发人员可以使用该参数来指示所需的批量处理选项（全部或全部不处理，或部分保存）；这些方法还返回调用例程可以读取的结果对象，以确定哪些记录处理不成功及其原因。Apex 和平台功能之间直接联系的其他示例包括内置电子邮件类和 XmlStream 类。

## 内部平台处理

在很大程度上，该平台的性能和规模都很好，因为 Salesforce 在构建它时牢记两个重要原则：

- 提供高效、大规模的基础平台功能。
- 帮助开发人员尽可能高效地完成所有工作。

该平台将这些原则纳入平台的独特处理架构，包括：

- 查询
- 搜索
- 批量操作
- 模式修改
- 多租户隔离
- 回收站

### 查询

大多数现代数据库系统通过使用基于成本的查询优化器来确定最佳查询执行计划，该优化器考虑了有关目标表和索引数据的相关统计数据。但是，传统的、基于成本的优化器统计数据是为单租户应用程序设计的，没有考虑到在多租户环境中执行查询的任何给定用户的数据访问特征。例如，对于高可见性用户（可以看到所有行的经理）和低可见性用户（只能看到与自己相关的行的销售人员），针对具有大量数据的对象的给定查询很可能会使用不同的执行计划来更有效地执行。

为了提供足够的统计数据来确定多租户系统中的优化查询执行计划，平台为每个组织的对象维护了一整套_优化器统计数据_（租户、小组和用户级别）。统计信息反映了特定查询可能访问的行数，仔细考虑了特定于组织的整体对象统计信息（例如，组织作为一个整体拥有的行总数），以及更精细的统计信息（例如，特定权限组或最终用户可能访问的行数）。

该平台还维护其他类型的统计数据，这些统计数据被证明有助于特定的查询。例如，平台维护所有自定义索引的统计信息，以显示相应字段中非空和唯一值的总数，以及显示每个列表值基数的选项列表字段的直方图。

当现有统计信息不存在或被认为没有帮助时，平台的优化器有一些不同的策略来帮助构建合理优化的查询。例如，当查询筛选对象的名称字段时，优化器可以使用 MT_Fallback_Indexes 表来高效地查找请求的行。在其他情况下，优化器将在运行时动态生成缺失的统计信息。

与优化器统计信息一起使用，平台的优化器还依赖于内部安全相关表（Groups、Members、GroupBlowout 和 CustomShare），这些表维护有关组织用户安全域的信息，包括给定用户的小组成员关系以及对象和行的自定义访问权限。这些信息对于确定每个用户的查询筛选器的选择性非常重要。有关平台嵌入安全模型的更多信息,请参阅[平台开发人员基本](https://developer.salesforce.com/page/Architecting_Force.com_Apps_A_Design_Primer)知识 Trailhead。

下图中的流程图说明了当平台处理对其中一个大堆表中的数据的请求时会发生什么，例如 MT_Data。该请求可能来自任意数量的源，例如 API 调用或存储的过程。首先，平台执行考虑多租户感知统计信息的“预查询”。然后，根据预查询返回的结果，服务构建最佳的基础数据库查询，以便在特定设置中执行。

<image style="width:100%;border:1px solid #e5e5e5;margin-top:1rem;margin-bottom:1rem" src="https://a.sfdcstatic.com/developer-website/prod/images/architect/multitenant-architecture-query-processing.png" alt="Query Processing">

如下表所示，平台可以通过四种不同的方式执行相同的查询，这取决于提交查询的用户和查询筛选条件的选择性。

<table>
    <tr>
        <td bgcolor=#d3d3d3 colspan="2"><b>查询前选择性测量</b></td>
        <td bgcolor=#d3d3d3 colspan="1"><b>写入最终数据库访问查询，强制...</b></td>
    </tr>
    <tr bgcolor=#f5f5f5>
        <td>用户</td>
        <td>筛选器</td>
        <td></td>
    </tr>
    <tr>
        <td>低</td>
        <td>低</td>
        <td>... 嵌套循环联接，使用用户可以看到的行视图驱动</td>
    </tr>
    <tr bgcolor=#f5f5f5>
        <td>低</td>
        <td>高</td>
        <td>... 使用与筛选器相关的索引</td>
    </tr>
    <tr>
        <td>高</td>
        <td>低</td>
        <td>... 有序的散列连接，使用 MT_ ⁇ A 驱动</td>
    </tr>
    <tr bgcolor=#f5f5f5>
        <td>高</td>
        <td>高</td>
        <td>... 使用索引相关筛选器</td>
    </tr>
</table>

### 搜索

用户希望交互式搜索功能扫描应用程序数据库的所有或选定范围，并返回响应时间低于秒的排名结果。为了向平台应用程序提供此功能，平台使用独立于事务引擎的_搜索引擎_。当您更新记录时，事务引擎会更新核心数据库，并将相关数据转发到搜索引擎进行索引。搜索记录时，搜索引擎会使用索引快速处理查询，并返回带有相关数据库记录链接的排名结果。

当应用程序更新文本字段中的数据（CLOB、名称等）时，称为索引服务器的后台进程池负责异步更新相应的索引，搜索引擎在核心事务引擎之外维护这些索引。为了优化索引过程，当事务提交时，平台将修改的文本数据块同步复制到内部“待索引”表中，从而提供一个相对较小的数据源，最大限度地减少索引服务器必须从磁盘读取的数据量。搜索引擎会自动为每个组织维护单独的索引。

根据索引服务器的当前负载和使用情况，文本索引更新可能会落后于实际事务。为了避免来自过时索引的意外搜索结果，该平台还维护了一个最近更新行的 MRU 缓存，系统在实现全文搜索结果时会考虑该缓存。该平台按用户和组织维护 MRU 缓存，以高效支持可能的搜索范围。

该平台的搜索引擎使用几种方法优化搜索结果中的记录排名。例如，系统会考虑执行搜索的用户的安全域，并在当前用户可以访问的行中增加权重。系统还可以考虑特定行的修改历史，并将更新更积极的行排到相对静态的行之前。用户可以根据需要选择对搜索结果加权，例如，更强调最近修改的行。

### 批量操作

当事务密集型应用程序批量组合和执行重复操作时，它们产生的开销更少，性能更好。例如，对比应用程序加载许多新行的两种方式。一种低效的方法是使用带有插入单个行的循环的例程，对每个行插入进行一个又一个的 API 调用。更高效的方法是创建行数组，并让例程通过一次 API 调用插入所有行。

对于开发人员来说，使用平台进行高效的批量处理很简单，因为它被烘烤成 API 调用。在内部，该平台还批量处理与显式批量操作相关的所有内部步骤。

该平台的批量处理引擎会自动考虑在前进过程中任何步骤中遇到的隔离故障。当批量操作以部分保存模式启动时，引擎会识别已知的开始状态，然后尝试执行流程中的每个步骤（批量验证字段数据、批量触发预触发器、批量保存记录等）。如果引擎在任何步骤中检测到错误，引擎会回滚违规操作和所有副作用，移除导致错误的行，并继续尝试批量处理剩余行子集。此流程会在每个连续阶段迭代，直到引擎提交行子集，没有任何错误。应用程序可以检查返回对象，以识别哪些行失败，以及它们引发了哪些异常。

**注意：**根据您的判断，全有或全无模式可用于批量操作。此外，批量操作期间触发器的执行受限制工作量的内部调控器的约束。

### 模式修改

某些类型的对象定义修改需要的不仅仅是简单的 UDD 元数据更新。在这种情况下，平台使用高效的机制来帮助减少对云数据库服务的整体性能影响。

例如，考虑当您将列的数据类型从选项列表修改为文本时在后台会发生什么。平台首先为列数据分配新时段，批量复制与当前值关联的选项列表标签，然后更新列的元数据，使其指向新时段。虽然所有这一切都发生，但数据访问正常，应用程序继续运行，没有任何明显的影响。

作为另一个示例，请考虑将累计汇总字段添加到对象时会发生什么。在这种情况下，平台使用高效的批量操作在后台异步计算初始汇总。当后台计算发生时，查看新字段的用户会收到平台当前正在计算字段值的指示。

### 多租户隔离和保护

为了防止恶意或无意地垄断共享的多租户系统资源，该平台拥有与平台代码执行相关的大量调控器和资源限制。例如，该平台密切监控代码脚本的执行，并限制它可以使用多少 CPU 时间、可以消耗多少内存、可以执行多少查询和 DML 语句、可以执行多少数学计算、可以调用多少出站 Web 服务等等。平台优化器认为执行起来过于昂贵的单个查询会向调用者抛出运行时异常。虽然这些限制听起来有些限制性，但它们对于保护所有相关应用程序的共享数据库系统的整体可扩展性和性能是必要的。从长远来看，这些措施有助于在开发人员中推广更好的编码技术，并为使用该平台的每个人创造更好的体验。例如，最初尝试编写循环的开发人员，由于资源限制，该循环一次更新一千行一行效率低下，他将收到运行时异常，然后开始使用平台的高效批量处理 API 调用。

为了进一步避免编写不良的应用程序带来的潜在系统问题，部署新的生产应用程序是一个严格管理的过程。在组织可以将新应用程序从开发状态过渡到生产状态之前，Salesforce 需要单元测试来验证应用程序的平台代码例程的功能。提交的单元测试必须覆盖不少于应用程序源代码的 75%。

Salesforce 在平台的 Sandbox 开发环境中执行提交的单元测试，以确定应用程序代码是否会对多租户群的性能和可扩展性产生负面影响。单个单元测试的结果指示基本信息，例如执行的行总数，以及关于测试未执行的代码的特定信息。

一旦应用程序的代码被 Salesforce 认证用于生产，应用程序的部署过程就由一个事务组成，该事务将所有应用程序的元数据复制到生产平台实例中，并重新运行相应的单元测试。如果流程的任何部分失败，平台只需回滚事务并返回异常，以帮助解决问题。

**注意：**Salesforce 在平台的每个开发版本中为每个应用程序重新运行单元测试，以主动了解新的系统功能和增强功能是否会破坏任何现有应用程序。

在生产应用程序上线后，平台的内置性能分析器会自动分析它，并向管理员提供相关的反馈。性能分析报表包含有关缓慢查询、数据操纵和子例程的信息，您可以查看并使用它们来调整应用程序功能。系统还会记录并向管理员返回有关运行时异常的信息，以帮助他们调试应用程序。

### 删除、取消删除和回收站

当应用程序从对象中删除记录时，平台只需通过修改 MT* 数据中的行的 IsDeleted 字段来标记要删除的行。此操作有效地将该行放入回收站中*。该平台允许您从回收站中恢复选定行长达 15 天，然后将其从 MT_Data 中永久删除。平台根据组织的存储限制来限制它为该组织维护的记录总数。

在操作删除涉及主-详细信息关系的父记录时，平台会自动删除所有相关子记录，前提是这样做不会破坏任何引用完整性规则。例如，当您删除 SalesOrder 时，平台会自动将删除级联到依赖 LineItems。如果您随后从回收站还原父记录，系统也会自动还原所有子记录。

相反，当您删除查找关系中涉及的引用父级记录时，平台会自动将所有依赖键设置为 null。如果您随后还原父级记录，平台会自动还原此前为空的查找关系，但在删除和还原操作之间重新分配的关系除外。

回收站也会存储已删除的字段及其数据，直到组织将其永久删除或经过一组天数（以先到者为准）。在此之前，整个字段及其所有数据都可以恢复。

## 平台基础设施

_敏捷性_是企业在现代世界取得成功的关键。Salesforce Platform 的基础层可帮助您的业务应用程序快速适应新的挑战，以便您可以继续关注您的业务，而不是基础设施。

### Hyperforce

基础_设施_(例如基本服务和计算资源)是支持 Salesforce 平台上层的隐藏底层技术。_Hyperforce_ 是 Salesforce Platform 基础设施,建立在 100% 可再生能源和零排放的基础上,解决关键的客户挑战,包括合规、Trust 和可扩展性

### 合规性

在多个地理位置运营的企业需要遵守新的、不断发展的、多样的数据管理法规。由于 Salesforce 正在越来越多的国家/地区部署 Hyperforce，目前取决于 AWS 地区的可用性，因此平台应用程序和用户可以以符合严格的数据存储或数据保护标准的方式运行他们的敏感工作负载。例如,通过 Hyperforce 支持_的 Salesforce 欧洲联盟_(欧盟)运营区,欧盟企业可以轻松地将数据保存在欧盟。

### Trust

安全性、可靠性和可用性是每个业务应用程序必须考虑的非功能要求，以实现对最终用户的Trust承诺。通过 Hyperforce，Salesforce 平台可让企业轻松交付受信任的业务应用程序。

- _安全性_ -- Hyperforce 对客户静态和传输中的数据进行本地端到端加密。Hyperforce 的 Zero Trust 架构强制实施严格的身份验证流程，确保对资源的无隐式访问。Hyperforce 使用_最小权限原则_ , 确保操作在正确的时间范围内被批准 , 具有正确的访问权限。
- _可靠性_ -- Hyperforce的每个实例都使用多个云可用性区域和加快事件反应的现代化方法,以提供高可用性和弹性的平台。
- _可用性_----Hyperforce 的现代 CI/CD 漏斗和蓝/绿应用程序版本将应用程序维护期减少到每年仅一分钟。

## 汇总

作为 Sales Cloud 和 Service Cloud 等应用程序的基础，Salesforce 是一个经过验证的应用程序开发平台，单个企业和服务提供商已经在该平台上为各种用例构建了数百万个业务应用程序，包括供应链管理、计费、会计、商务、合规跟踪、人力资源管理和索赔处理。该平台独特的多租户元数据驱动架构专为云设计，可靠安全地支持关键任务互联网规模应用程序。使用基于标准的 API 和本地开发工具，平台开发人员可以轻松构建现代 Web 或移动应用程序的所有组件，包括应用程序的数据模型（包括对象和关系）、业务逻辑（包括工作流和验证）、与其他应用程序的集成等。

自成立以来，该平台已经由 Salesforce 的工程师针对多租户进行了优化，其功能允许平台应用程序扩展以满足不断变化的业务需求。集成系统功能 — 例如批量数据处理 API、Apex、全文搜索引擎和独特的查询优化器 — 有助于使依赖应用程序高效和可扩展，开发人员只需很少或根本不用努力。

Salesforce 用于部署生产应用程序的受管方法确保了依赖于该平台的所有应用程序都具有出色的性能、可扩展性和可靠性。Salesforce 不断监控和收集平台应用程序的运营信息，以帮助推动增量改进和新系统功能，从而立即使现有和新应用程序受益。

## 关于作者

Steve Bobrowski 是一位成功的企业家和技术领导者，自 2008 年以来为多家领先的企业软件公司工作，包括担任 Salesforce 的各种角色。如今,Steve 在 Salesforce 的 CTO 办公室工作，帮助制定公司的技术架构战略。

Tom Leddy 是 Salesforce 的架构师。他通过帮助创建资源、工具和指导来支持全球 Salesforce 架构师社区，以帮助架构师完成他们的最佳工作。在 [Twitter](https://twitter.com/tomruns_262) 上与 Tom 联系。
