Apex Transactions 确保数据的完整性。Apex 代码作为原子的一部分运行 交易。调速器执行限制确保有效利用资源 Lightning Platform 多租户平台。
大多数调控器限制是按事务设置的,有些则不是,例如 24 小时限制 限制。
为确保 Apex 遵守调速器限制,应使用某些设计模式, 例如查询中的批量调用和外键关系。
- Apex 事务
Apex 事务表示作为单个单元执行的一组操作。事务中的所有 DML 操作都必须成功完成。如果在一个操作中发生错误,则回滚整个事务,并且不会将任何数据提交到数据库。事务的边界可以是触发器、类方法、匿名代码块、Visualforce 页面或自定义 Web 服务方法。 - 执行调控器和限制
由于 Apex 在多租户环境中运行,因此 Apex 运行时引擎会严格执行限制,以便失控的 Apex 代码或进程不会独占共享资源。如果某些 Apex 代码超出限制,则关联的调控器会发出无法处理的运行时异常。 - 设置调控器限制电子邮件警告
您可以指定组织中的用户在调用超过 50% 的已分配调控器限制的 Apex 代码时接收电子邮件通知。仅检查每个请求的限制以发送电子邮件警告;不检查每个组织的限制,例如并发长时间运行的请求。这些电子邮件通知不计入每日单封电子邮件限制。 - 在调控器执行限制
内运行 Apex 当您在多租户云环境(如 Lightning 平台)中开发软件时,您不必扩展代码,因为 Lightning 平台会为您完成这些工作。由于资源在多租户平台中共享,因此 Apex 运行时引擎会强制执行一些限制,以确保没有一个事务独占共享资源。
Apex 事务
Apex 事务表示一组操作,这些操作作为 单个单元。事务中的所有 DML 操作都必须成功完成。如果错误 在一次操作中发生,整个事务被回滚,并且没有数据被提交到 数据库。事务的边界可以是触发器、类方法、匿名 代码块、Visualforce 页面或自定义 Web 服务方法。
注意
付款交易是 DML 操作错误的例外。即使出现错误 发生时,数据已提交并生成付款记录,因为交易具有 已经发生在支付网关上。
在事务边界内发生的所有操作都表示 操作,包括对外部代码的调用,例如在 事务边界。例如:自定义 Apex Web 服务方法导致触发器 触发,这反过来又调用类中的方法。在本例中,所有更改都是 只有在事务中的所有操作都完成执行后才提交到数据库 并且不会导致任何错误。如果在任何中间步骤中发生错误, 所有数据库更改都将回滚,并且不会提交事务。
Apex 事务有时称为执行上下文。本指南使用 术语 Apex 交易。
交易有什么用?
当多个操作相关且全部或无操作时,事务非常有用 的操作已提交。目标是使数据库保持一致 州。有许多业务方案可以从事务处理中受益。 例如,将资金从一个银行账户转移到另一个银行账户是很常见的 场景。它涉及从第一个账户中借记并记入第二个账户 与要转移的金额。这两个操作必须一起提交到 数据库。如果借方操作成功而贷方操作失败,则 账户余额变得不一致。
例
此示例演示当最后一个操作导致验证时,如何回滚方法中的所有 DML 操作 规则失败。在此示例中,方法是事务边界,即在此方法中运行的所有代码 要么将所有更改提交到平台数据库,要么回滚所有更改。在 在本例中,我们添加了一个发票对帐单,其中包含铅笔商品的行项目。 该行项目用于购买Units_Sold__c中指定的 5,000 支铅笔 字段,这比整个铅笔库存的 1,000 多。这个例子 假设已设置验证规则来检查 商品足以支付新购买的费用。insertinvoice
由于此示例尝试购买的铅笔 (5,000) 多于库存商品 (1,000),验证规则将失败并引发异常。代码执行在 此点以及在此异常之前处理的所有 DML 操作都将回滚。 发票对帐单和行项不会添加到数据库中,并且它们的 DML 操作将滚动 返回。insert在开发者控制台中,执行静态方法。
invoice
// Only 1,000 pencils are in stock.
// Purchasing 5,000 pencils cause the validation rule to fail,
// which results in an exception in the invoice method.
Id invoice = MerchandiseOperations.invoice('Pencils', 5000, 'test 1');
这个定义就是方法。这 由于验证规则失败,总库存的更新会导致异常。如 因此,发票对帐单和行项将回滚,并且不会插入 添加到数据库中。invoice
public class MerchandiseOperations {
public static Id invoice( String pName, Integer pSold, String pDesc) {
// Retrieve the pencils sample merchandise
Merchandise__c m = [SELECT Price__c,Total_Inventory__c
FROM Merchandise__c WHERE Name = :pName LIMIT 1];
// break if no merchandise is found
System.assertNotEquals(null, m);
// Add a new invoice
Invoice_Statement__c i = new Invoice_Statement__c(
Description__c = pDesc);
insert i;
// Add a new line item to the invoice
Line_Item__c li = new Line_Item__c(
Name = '1',
Invoice_Statement__c = i.Id,
Merchandise__c = m.Id,
Unit_Price__c = m.Price__c,
Units_Sold__c = pSold);
insert li;
// Update the inventory of the merchandise item
m.Total_Inventory__c -= pSold;
// This causes an exception due to the validation rule
// if there is not enough inventory.
update m;
return i.Id;
}
}
执行调控器和限制
因为 Apex 在多租户环境中运行,Apex 运行时引擎严格执行限制,因此 失控的 Apex 代码或进程不会垄断共享资源。如果某些 Apex 代码 超过限制,关联的调控器会发出运行时异常,而该异常不能 处理。Apex 限制或调控器跟踪并强制执行 下表和部分。
- 每笔交易最高限额
- 每笔交易认证托管 包装限制
- 闪电平台Apex 限制
- 静态Apex限制
- 特定尺寸的Apex限制
- 其他Apex限制
除了核心的 Apex 调控器限制外,本文稍后还包括电子邮件限制和推送通知限制 主题,以方便您。
每笔交易最高限额
这些限制计入每笔 Apex 交易。对于 Batch Apex,这些 每次执行方法中的一批记录时,都会重置限制。execute
下表列出了同步 Apex 和 异步 Apex(Batch Apex 和未来方法),当它们不同时。否则 此表仅列出了适用于同步和异步 Apex 的一个限制。
注意
- 尽管计划的 Apex 是一项异步功能,但同步限制适用于 计划的 Apex 作业。
- 对于批量 API 和批量 API 2.0 事务,有效限制是 同步和异步限制。例如,Bulk Apex 作业的最大数量 添加到队列中时,是 同步限制 (50),高于异步限制 (1)。System.enqueueJob
1在具有父子关系子查询的 SOQL 查询中,每个 父子关系计为一个额外的查询。这些类型的查询限制为 是顶级查询数量的三倍。子查询的限制对应于 返回的值。这些关系查询的行计数对 整体代码执行。此限制不适用于自定义元数据类型。在单个 Apex 中 事务,自定义元数据记录可以有无限的 SOQL 查询。除了静态 SOQL 语句、对以下方法的调用计入 SOQL 语句数 在请求中发出。
Limits.getLimitAggregateQueries()
- Database.countQuery,Database.countQueryWithBinds
- Database.getQueryLocator,Database.getQueryLocatorWithBinds
- Database.query,Database.queryWithBinds
- Approval.process
- Database.convertLead
- Database.emptyRecycleBin
- Database.rollback
- Database.setSavePoint
- delete和Database.delete
- insert和Database.insert
- merge和Database.merge
- undelete和Database.undelete
- update和Database.update
- upsert和Database.upsert
- EventBus.publish对于平台事件 配置为在提交后发布
- System.runAs
3递归Apex,不会用 、 、 触发任何触发器 或语句,存在于单个 调用,使用单个堆栈。相反,触发触发器的递归 Apex 会生成 在新的 Apex 调用中触发。新的调用与 导致它触发的代码。生成 Apex 的新调用是一项更昂贵的操作 而不是单次调用中的递归调用。因此,对 这些类型的递归调用的堆栈深度。insertupdatedelete
5计算 Salesforce 上所有执行的 CPU 时间 在一个 Apex 事务中发生的应用程序服务器。CPU 时间是针对 执行 Apex 代码,以及从此代码调用的任何进程,例如 package 代码和工作流。CPU 时间对于事务是私有的,并且与其他事务隔离 交易。不占用应用程序服务器 CPU 时间的操作不计算在内 朝向 CPU 时间。例如,在数据库中花费的执行时间部分 DML、SOQL 和 SOSL 不计算在内,Apex 标注的等待时间也不计算在内。应用程序服务器 在 DML 操作中花费的 CPU 时间计入 Apex CPU 限制,但不计入预期 意义重大。批量 API 和批量 API 2.0 对 CPU 时间使用唯一的调控器限制 Salesforce 服务器,最大值为60,000毫秒。
注意
- 限制分别适用于每个 .testMethod
- 确定代码的代码执行限制,同时 它正在运行,请使用 Limits 方法。例如,可以使用该方法确定 程序已调用的 DML 语句。或者,您可以使用该方法确定 代码可用的 DML 语句总数。getDMLStatementsgetLimitDMLStatements
每笔交易认证的托管包限制
经认证的托管软件包 – 已通过 AppExchange 的安全审查 – 针对大多数每个事务的限制,获取自己的一组限制。 Salesforce ISV 合作伙伴开发经过认证的托管软件包,这些软件包安装在您的组织中 从 AppExchange 并具有唯一的命名空间。
以下示例说明了单独的认证托管 DML 语句的包限制。如果您安装经过认证的托管软件包,则所有 Apex 该包中的代码有自己的 150 个 DML 语句。这些 DML 语句是附加的 到组织的本机代码可以执行的 150 个 DML 语句。此限制增加意味着更多 超过 150 个 DML 语句可以在单个事务期间执行,如果代码来自 package 和您的本机组织都会执行。同样,经过认证的托管包会获得其 除了组织的原生代码限制外,还拥有同步 Apex 的 100-SOQL 查询限制 100 个 SOQL 查询。
认证命名空间的数量没有限制 在单个事务中调用。但是,可以在 每个命名空间不得超过每个事务的限制。对 事务中跨命名空间可执行的累计操作数。这 累积限制是每个命名空间限制的 11 倍。例如,如果每个命名空间 SOQL 查询限制为 100 个,单个事务最多可以执行 1,100 个 SOQL 查询。在 在这种情况下,累积限制是每个命名空间限制 100 的 11 倍。这些查询 可以跨无限数量的命名空间执行,只要任何一个命名空间 查询不超过 100 个。累积限制不会影响以下限制 在所有命名空间之间共享,例如对最大 CPU 时间的限制。
注意
- 这些跨命名空间限制仅适用于经过认证的托管命名空间 包。
- 未经认证的包中的命名空间没有自己单独的调控器限制。 他们使用的资源继续计入 组织的自定义代码。
描述 | 累积跨命名空间限制 |
---|---|
发出的 SOQL 查询总数 | 1,100 |
检索到的记录总数Database.getQueryLocator | 110,000 |
发出的 SOSL 查询总数 | 220 |
发出的 DML 语句总数 | 1,650 |
标注(HTTP 请求或 Web 服务调用)的总数 交易 | 1,100 |
方法总数 允许sendEmail | 110 |
对于经过认证的托管软件包,所有每个事务的限制都单独计算在内,但以下情况除外:
- 总堆大小
- 最大 CPU 时间
- 最大交易执行时间
- 唯一命名空间的最大数量
这些限制对整个事务都很重要,无论有多少经过认证的托管事务 包在同一事务中运行。
来自 AppExchange 的软件包中的代码,不是由 Salesforce ISV 合作伙伴创建的,也不是由 经过认证,没有自己单独的调速器限制。包使用的任何资源 计入组织管理器总数限制。累积资源消息和警告电子邮件 也是基于托管包命名空间生成的。
有关 Salesforce ISV 合作伙伴包的详细信息,请参阅 Salesforce 合作伙伴计划。
Lightning 平台 Apex 限制
此表中的限制不是 特定于 Apex 交易;Lightning Platform 强制执行这些限制。
1对于 Batch Apex,方法执行包括 、 和 方法的执行。startexecutefinish此限制适用于您的整个组织,并且是共享的 使用所有异步 Apex:Batch Apex、Queueable Apex、scheduled Apex 和 未来的方法。计入此限制的许可证类型包括完整 Salesforce 和 Salesforce Platform 用户许可证、应用程序订阅用户 许可证、仅限 Chatter 用户、身份用户和公司社区 用户。
2如果在 10 个长时间运行时启动了更多事务 事务仍在运行,但被拒绝。HTTP 标注处理时间不是 在计算此限制时包括在内。
3提交批处理作业后,它们将保留在弹性中 在系统将它们排队等待处理之前进行排队。
4尚未启动的批处理作业仍保留在队列中 直到它们开始。如果正在运行多个作业,则此限制不会导致任何 批处理作业失败。批处理方法 Apex 作业仍并行运行。execute
5此限制适用于异步运行的测试。这 测试组包括通过 Salesforce 用户界面启动的测试 包括开发人员控制台或使用 SOAP 插入 ApexTestQueueItem 对象 API接口。
6检查有多少个异步 Apex 执行 可用,请向 REST API 资源发出请求或使用 Apex 方法或 .查看清单 《REST API 开发人员指南》中的组织限制和《Apex 参考指南》中的 OrgLimits 类。limitsOrgLimits.getAll()OrgLimits.getMap()
静态Apex限制
2 平台事件和更改的 Apex 触发器批处理大小 数据捕获事件为 2,000。
特定尺寸的Apex限制
1此限制不适用于第一代 (1GP) 中的 Apex 代码,或者 第二代 (2GP) 托管软件包。这些类型的包中的代码属于 命名空间与组织中的代码不同。此限制也不适用于任何代码 包含在使用 @isTest 注释定义的类中。
其他Apex限制
在 Apex 中连接对于命名空间中的类,每个 写入操作会根据 Apex 调控器限制消耗一个 DML 语句。 方法调用也受费率影响 限制。 速率限制与 Connect 匹配 REST API 速率限制。两者都有每个用户、每个命名空间、每小时的速率限制。当你 超过速率限制,则抛出 A。您的 Apex 代码必须捕获和 处理此异常。ConnectApiConnectApiConnectApiConnectApi.RateLimitExceptionData.com 清洁如果您使用 Data.com Clean 产品及其自动化作业,请考虑如何使用 Apex触发器。如果您在运行的客户、联系人或潜在顾客记录上有 Apex 触发器 SOQL 查询,SOQL 查询可能会干扰这些对象的清理作业。你 Apex 触发器(组合)每批不得超过 200 个 SOQL 查询。如果他们这样做,你的 该对象的清理作业失败。此外,如果触发器调用方法,则每批调用次数限制为 10 次。futurefuture事件报告事件报告为非 系统管理员为20,000;对于系统管理员,100,000。Apex 测试中的MAX_DML_ROWS限制可以在单个 同步 Apex 测试执行上下文,限制为 450,000。例如,Apex 类可以有 45 个方法,每个方法插入 10,000 行。如果达到限制,您会看到 此错误: 。Your runallTests is consuming too many DB resourcesSOQL 查询性能为了获得最佳性能,SOQL 查询必须是有选择性的,尤其是对于内部的查询 触发器。为了避免长时间的执行,系统可以终止非选择性 SOQL 查询。当触发器中的非选择性查询时,开发人员会收到错误消息 对包含超过 200,000 条记录的对象执行。为避免此错误, 确保查询是有选择性的。查看更高效的 SOQL 查询。
电子邮件限制
入站电子邮件限制
1电子邮件服务的电子邮件的最大大小各不相同 取决于字符集和正文部分的传输编码。电子邮件的大小 邮件包括电子邮件标题、正文、附件和编码。因此,一个 带有 35 MB 附件的电子邮件可能超过电子邮件的 25 MB 大小限制 在考虑标头、正文和编码之后。什么时候 定义电子邮件服务时,请注意以下几点:
- 电子邮件服务仅处理在其 地址。
- Salesforce 限制 所有电子邮件服务(包括按需电子邮件到案例)都可以处理 日常。超过此限制的邮件将被退回、丢弃或排队等待 第二天处理,具体取决于您如何为每个电子邮件服务配置失败响应设置。Salesforce 通过将 用户许可证数量增加 1,000 个;最大 1,000,000。例如,如果您有 10 个许可证,您的组织最多可以处理 10,000 封电子邮件 日。
- 您在沙盒中创建的电子邮件服务地址无法复制到 生产组织。
- 对于每个电子邮件服务,您可以告诉 Salesforce 将错误电子邮件发送到 指定的地址,而不是发件人的电子邮件地址。
- 电子邮件服务拒绝电子邮件并通知发件人 如果电子邮件(正文文本、正文 HTML 和附件组合)超过 大约25兆字节 (因语言和性格而异 设置).
出站电子邮件:使用 Apex 发送的单封电子邮件和群发电子邮件的限制
每个获得许可的组织都可以将一封电子邮件发送到 每天最多 5,000 个外部电子邮件地址基于 格林威治标准时间(GMT)。对于在 Spring ’19 之前创建的组织,将强制执行每日限制 仅适用于通过 Apex 和 Salesforce API 发送的电子邮件,REST 除外 应用程序接口。对于在 Spring ’19 及之后创建的组织,每日限制为 也适用于电子邮件警报、简单电子邮件操作、发送电子邮件 流中的操作和 REST API。如果其中一封新计数的电子邮件 无法发送,因为您的组织已达到限制,我们会通知您 并添加一个条目到调试日志。 使用 Salesforce 中的电子邮件作者或作曲家不计入此内容 限制。 发送没有限制 向联系人、潜在顾客、个人帐户和用户发送一封电子邮件 直接从客户、联系人、潜在客户、商机、案例、 营销活动或自定义对象页面。 在 Developer Edition 组织中 以及在试用期内评估 Salesforce 的组织,您可以 最多发送到50每天的收件人,每封电子邮件最多可以有 15 个 收件人。.发送电子邮件时,请牢记以下注意事项:
- 发送时 单个电子邮件,您最多可以指定150每个 SingleEmailMessage 中“收件人”、“抄送”和“密件抄送”字段中的收件人。每 字段也仅限于4,000 字节.
- 如果您使用 SingleEmailMessage 通过电子邮件发送 org 的内部用户,指定用户的 ID in setTargetObjectId 表示电子邮件 不计入每日限额。然而 在 setToAddresses 中指定内部用户的电子邮件地址意味着电子邮件这样做 计入限制。
- 您可以向最多 5,000 个外部电子邮件地址发送群发电子邮件和列表电子邮件 每个获得许可的 Salesforce 组织的天数。一天是根据格林威治标准时间 (GMT) 计算的。
- 单封电子邮件、群发电子邮件和列表电子邮件限制计算重复的电子邮件地址。为 例如,如果您的电子邮件中有 10 倍的 johndoe@example.com 计为 10 个。
- API 或 Apex 单个电子邮件最多可以发送到 5,000 个外部电子邮件地址 日。
- 您可以通过 UI 向组织的内部发送无限量的电子邮件 用户,包括门户用户。
- 您只能向联系人、个人帐户、潜在客户和您的 org 的内部用户。
- 在 Developer Edition 组织和试用期内评估 Salesforce 的组织中,您可以发送 每个组织每天使用群发电子邮件和列表电子邮件的外部电子邮件收件人不超过 10 个。
- 您无法使用 Visualforce 电子邮件模板发送群发电子邮件。
推 通知限制
一个组织最多可以发送 20,000 个 iOS 推送和 10,000 个 Android 推送 每小时通知(例如,4:00 到 4:59 UTC)。
只有可送达通知才计入此限制。例如,向 1,000 发送通知 贵公司的员工,但有 100 名员工尚未安装移动应用。 只有发送给已安装移动应用程序的 900 名员工的通知才算数 朝这个极限迈进。
通过测试推送生成的每个测试推送通知 通知页面仅限于单个收件人。测试推送通知计入 org 的每小时推送通知限制。
当组织的每小时推送通知限制为 满足,仍会通过以下方式创建任何其他通知以进行应用内显示和检索 REST API。
设置调速器限制电子邮件警告
您可以指定组织中的用户在以下情况下接收电子邮件通知 调用超过分配调控器的 50% 的 Apex 代码 限制。仅按请求 检查发送电子邮件警告的限制;每个组织的限制,例如并发长时间运行 不检查请求。这些电子邮件通知不计入每日单封电子邮件 限制。
- 以管理员用户身份登录 Salesforce。
- 在“设置”中,在“快速查找”框中输入, ,然后选择用户。Users
- 单击用户名称旁边的编辑以接收电子邮件 通知。
- 选择“发送 Apex 警告电子邮件”选项。
- 点击保存。
注意
当前会检查这些限制以发送电子邮件警告。
SOQL总数 发出的查询
SOQL 查询检索的记录总数
总数 发出的 SOSL 查询
发出的 DML 语句总数
记录总数 作为 DML 语句的结果进行处理,或者Approval.processdatabase.emptyRecycleBin
总堆大小
标注总数 (HTTP 请求或 Web 服务调用)在事务中
允许的方法总数sendEmail
最大方法数 每个 Apex 允许的注释 调用future
添加到队列的最大 Apex 作业数System.enqueueJob
检索到的记录总数Database.getQueryLocator
手机总数 Apex 推送调用
在调控器执行限制内运行 Apex
当您在多租户云环境(如 Lightning)中开发软件时 平台,您不必扩展代码,因为 Lightning 平台会为您完成。 由于资源在多租户平台中共享,因此 Apex 运行时引擎会强制执行 一些限制,以确保没有一个事务垄断共享资源。
您的 Apex 代码必须在这些预定义的执行限制内执行。如果调速器限制 超出,则会引发无法处理的运行时异常。通过以下 最佳做法,可以避免达到这些限制。想象一下,你必须洗 100件T恤。你会一个接一个地洗——每堆衣服洗一件,还是会 您将它们分批分组,只加载几次?在云中编码的好处是 您将学习如何编写更高效的代码并浪费更少的资源。
调控器执行限制是针对每个事务的。例如,一笔交易可以发出 最多 100 个 SOQL 查询和 150 个 DML 语句。还有其他一些限制 不受事务限制,例如可以排队的批处理作业数或 一次处于活动状态。
以下是编写不超过一定范围的代码的一些最佳实践 调速器限制。
批量 DML 呼叫
对 sObject 列表而不是每个单独的 sObject 进行 DML 调用使它 不太可能达到 DML 语句限制。下面是一个示例, 不会批量化 DML 操作,下一个示例显示了建议的 调用 DML 语句的方式。
例:对单个 sObject 的 DML 调用
for 循环遍历 List 变量中包含的行项。对于每个行项,它会为 Description__c字段,然后更新订单项。如果列表包含超过 150 个项目,第 151 个更新调用返回超出 DML 的运行时异常 语句限制为 150。我们如何解决这个问题?查看第二个示例的简单 溶液。liList
for(Line_Item__c li : liList) {
if (li.Units_Sold__c > 10) {
li.Description__c = 'New description';
}
// Not a good practice since governor limits might be hit.
update li;
}
推荐的替代方案:对 sObject 列表的 DML 调用
此增强版本的 DML 调用对整个列表执行更新,该列表 包含更新后的订单项。它首先创建一个新列表,然后在 循环将每个更新行项添加到新列表中。然后,它执行批量 更新新列表。
List<Line_Item__c> updatedList = new List<Line_Item__c>();
for(Line_Item__c li : liList) {
if (li.Units_Sold__c > 10) {
li.Description__c = 'New description';
updatedList.add(li);
}
}
// Once DML call for the entire list of line items
update updatedList;
更高效的 SOQL 查询
将 SOQL 查询放在循环块中 这不是一个好的做法,因为 SOQL 查询每次迭代都执行一次 并可能超过每个事务 100 个 SOQL 查询的限制。以下是 对 中的每个项目运行 SOQL 查询的示例,效率不高。另一个例子是 给定一个修改后的查询,该查询仅使用一个 SOQL 检索子项 查询。forTrigger.new
例:子项查询效率低下
此示例中的循环循环访问 中的所有发票对帐单。在循环中执行的 SOQL 查询检索 每个发票对帐单的子行项目。如果超过 100 份发票对帐单 插入或更新,并因此包含在 中,这会导致运行时异常,因为达到 SOQL 限制。第二个示例通过创建另一个 SOQL 来解决此问题 只能调用一次的查询。forTrigger.newTrigger.new
trigger LimitExample on Invoice_Statement__c (before insert, before update) {
for(Invoice_Statement__c inv : Trigger.new) {
// This SOQL query executes once for each item in Trigger.new.
// It gets the line items for each invoice statement.
List<Line_Item__c> liList = [SELECT Id,Units_Sold__c,Merchandise__c
FROM Line_Item__c
WHERE Invoice_Statement__c = :inv.Id];
for(Line_Item__c li : liList) {
// Do something
}
}
}
推荐的替代方案:使用一个 SOQL 查询查询子项
此示例绕过了为每个项目调用 SOQL 查询的问题。它 有一个修改后的 SOQL 查询,该查询检索属于其中的所有发票对帐单,并获取其行 项目通过嵌套查询。这样,只执行一个 SOQL 查询,并且 我们仍然在我们的极限之内。Trigger.new
trigger EnhancedLimitExample on Invoice_Statement__c (before insert, before update) {
// Perform SOQL query outside of the for loop.
// This SOQL query runs once for all items in Trigger.new.
List<Invoice_Statement__c> invoicesWithLineItems =
[SELECT Id,Description__c,(SELECT Id,Units_Sold__c,Merchandise__c from Line_Items__r)
FROM Invoice_Statement__c WHERE Id IN :Trigger.newMap.KeySet()];
for(Invoice_Statement__c inv : invoicesWithLineItems) {
for(Line_Item__c li : inv.Line_Items__r) {
// Do something
}
}
}
SOQL For 循环
使用 SOQL for 循环以 200 条为一组对记录进行操作。这有助于避免堆 大小限制为 6 MB。请注意,此限制适用于同步运行的代码,它是 对于异步代码执行,该值更高。
例:不带 for 循环的查询
以下是检索所有商品和 将它们存储在 List 变量中。如果退货商品尺寸较大 并且返回了大量它们,可能会达到堆大小限制。
List<Merchandise__c> ml = [SELECT Id,Name FROM Merchandise__c];
推荐的替代方案:for 循环中的查询
为了防止这种情况发生,第二个版本使用了 SOQL for 循环,该循环 以 200 条记录为一组循环访问返回的结果。这样可以减小尺寸 现在包含 200 的 list 变量 项,而不是查询结果中的所有项,并为每个项重新创建 批。ml
for (List<Merchandise__c> ml : [SELECT Id,Name FROM Merchandise__c]){
// Do something.
}