编写高效的查询
学习目标
完成本单元后,您将了解:
- Force.com 查询优化器如何优化查询性能。
- 使用选择性查询对查询性能的影响。
- 如何使用查询计划工具来评估搜索查询。
限制
高效的查询不仅性能更好,而且有助于确保您不会遇到调控器限制的问题。记住,这是一个多租户平台,每个人都必须共享空间。最能让系统瘫痪的头号杀手是性能很差的查询。这正是调控器限制发挥作用的地方。
可以把调控器限制想象成一种资源裁判。他们确保每个人都遵守游戏规则,平等地分享资源蛋糕。
在本单元,您将了解可以做些什么来优化您的搜索查询,以免受到限制。
Force.com 查询优化器
Salesforce 的后台数据库使用 Oracle,但是 Force.com 使用它自己的查询优化器版本来评估基于成本的查询。跟大多数基于成本的查询优化器一样,Salesforce 所使用的查询优化器依赖采集的数据统计。大多数统计每周收集一次,但是系统也会生成每小时缓存的预查询。
查询优化器评估 SOQL 查询和 SOSL 搜索。它在某种程度上充当交警的角色,把查询路由给合适的索引。它查看每一条进来的查询,为它识别到的每个潜在查询路径分配一个成本值。然后,它用这些成本来确定采用哪个执行计划。
我们不会说谎。查询优化器选择执行计划以及处理阈值的方式可能有点复杂。不过我们知道作为 .NET 开发人员,您能够接受这个挑战。本单元结束后,您可以去浏览资源部分的链接,想学多深,就学多深。
最佳实践
我们知道 .NET 开发人员喜欢思考最佳实践。你们喜欢挑战自我,总是在寻找做事情的最佳方式。我们理解这一点。因此我们认为您会喜欢学习为了构建快速、高效的搜索查询,需要采用什么最佳实践。
编写选择性查询
在第一单元中,我们介绍了 SOQL 语句以及您如何利用 WHERE 子句应用筛选器。您甚至可以用 AND 和 OR 子句结合多个字段。
我们知道您不会因此而感到惊讶,在 WHERE 子句里放更多字段是好事。显然,您的查询返回的数据越少越好。不过,您可能不知道,并非所有字段都是一样的。有些字段是“威力”字段。如果您在 WHERE 子句中使用这些威力字段,查询会超级快。
是什么让这些威力字段如此强大呢?当然是索引。
对于所有标准和自定义表格,某些字段自动被标记,以建立索引。这些字段包括:
索引字段 | 描述 |
---|---|
Id | 系统生成的唯一的 18 个字符字段。这是对象的主键。 |
Name | 基于文本的字段。 |
OwnerId | 引用对象的所有者。 |
CreatedDate | 创建记录的日期和时间。 |
SystemModstamp | 只读字段,包含最后一次更新记录的日期。该字段加索引,而类似的 LastModifiedDate 没有,所以可以考虑在您的查询中使用这个字段。 |
RecordType | RecordType 的 ID。RecordType 用来向特定用户提供不同的 UI 结果。 |
主-详细信息字段 | 外键字段,用来注明主-详细信息关系 |
查找字段 | 外键字段,用来注明查找关系 |
唯一字段 | 自定义字段可以在创建的时候标记为唯一的,这会自动给它们加上索引。 |
外部 ID 字段 | 跟唯一字段一样,这些自定义字段可以标记为外部 ID,主要用于集成目的。 |
每次在查询的 WHERE 子句中使用这些索引字段中的某一个时,都提高了查询被视为选择性,使用索引而不是全表扫描的几率。当您在处理大型数据库时,我们再怎么强调这一点的重要性都不为过。
备注:Salesforce 客户可以向 Salesforce 支持请求自定义索引,可以创建一个支持个案,包含带索引字段的 SOQL 查询。
索引选择性例外
在查询中使用索引字段并不一定是最佳选择。您可以在查询中做一些事情,使它们不是选择性的,从而容易产生可怕的全表扫描。编写查询时,要尽量避免这些事情。
- 空行查询——搜索某个字段为空白或空值的记录的查询。例如:
SELECT Id, Name FROM Account WHERE Custom_Field__c = null
- 否定筛选运算符——在您的查询中使用运算符,如 !=, NOT LIKE,或 EXCLUDES。例如:
SELECT CaseNumber FROM Case WHERE Status != ‘New’
- 开头通配符——开头使用通配符的查询,比如这个:
SELECT Id, LastName, FirstName FROM Contact WHERE LastName LIKE ‘%smi%’
- 带比较运算符的文本字段——使用比较运算符,如 >, <, >=, or <=,带基于文本的字段。例如:
SELECT AccountId, Amount FROM Opportunity WHERE Order_Number__c > 10
查询计划工具
我们的 Developer Console 包含一个简洁的小工具可以让您的查询提速。它让您一窥幕后,了解查询优化器是如何工作的。查询计划工具默认禁用。启用它的步骤如下。
- 从“设置”菜单中,选择 Developer Console 打开 Developer Console。
- 在 Developer Console 中,选择 Help(帮助)> Preferences(首选项)。
- 选择 Enable Query Plan(启用查询计划),确保它设为 true。
- 单击保存。
- 在 Query Editor(查询编辑器)选项卡中,确认 Query Plan(查询计划)按钮现在在 Execute(执行)按钮旁边。
启用查询计划工具后,您就可以用它来评估查询了。我们先用它来评估一个性能很差的查询。
- 在 Developer Console 中,单击底部窗格中的 Query Editor(查询编辑器)选项卡。
- 删除现有代码,插入以下片段:
SELECT Id, CaseNumber FROM Case WHERE Status != 'New'
- 单击 Query Plan(查询计划)。
Query Plan(查询计划)对话框显示一个表格,列示查询成本,它将做 TableScan。这不是好事。查看底部窗格中的备注,进一步解释结果。
现在我们来看一下另一条查询,跟第一条查询获得同样的结果。
- 单击底部窗格中的 Query Editor(查询编辑器)选项卡。
- 删除现有代码,插入以下片段:
SELECT Id, CaseNumber FROM Case WHERE IsClosed = true
- 单击 Query Plan(查询计划)。
Query Plan(查询计划)对话框显示一个表格,列示查询成本,不过这一次您看到显示了另一行,提示可以使用索引。
我们通过查询计划运行的这两条查询提取了同样的行数,但是由于我们选择的字段和运算符,执行计划却相差很大。这些差别看起来很小,是因为开发组织中的数据量很小,但是当您开始比较有好几百万条记录的组织中的查询时,这些差别可能是天壤之别。
欲进一步了解查询计划工具中的每一列反映什么,请查看资源部分关于查询计划工具的链接。
了解详细信息
要尽量避免创建含非确定性公式字段的查询。公式字段是自定义字段,允许您在运行时动态计算某个字段的值。这些类型字段往往在大部分组织中都很流行,很容易被滥用。当某个公式字段的值随着时间变化时,它被认为是非确定性的。更多信息请见资源部分关于 SOQL 最佳实践的链接:“空值和公式字段”。
遗憾的是,您无法使用“查询计划”工具评估 SOSL 查询,但是这并不意味着您不用考虑这些查询类型的性能。请参考资源部分的“最佳实践”和“性能技巧”链接,进一步了解写 SOSL 查询时应该避免的坑。