超大量数据导入优化策略
Salesforce和很多其他系统都可以很好的协作。在协作过程中,数据的导入导出便成为了一个关键的步骤。
当客户的业务量非常大的时候,会有将超大量数据导入Salesforce的需求。对于超大量数据的导入,必须做好万全的准备,才能保证导入过程的顺利与高效。
对于超大量数据导入过程,可以从多个方面进行优化。它们也适用于Salesforce的其他功能。
精简表
有些时候,业务中涉及到大量、复杂的关系。在Salesforce中设计对应的对象时,可能会出现很多对象,它们互相之间存在复杂的联系。在进行查询的时候,Salesforce内部会将存储这些对象和关系的数据表进行联合(JOIN)操作,从而会消耗很多系统资源。
采用“精简表”(Skinny Table)可以对这种情况进行优化。精简表从若干数据表中提取相关字段,集中保存起来,使得Salesforce在进行查询时不需要进行多表的联合,而是直接从精简表中查询,提高了效率。
比如:在Salesforce中对象的标准字段和自定义字段是分开存放的。对于Account对象,有表A(存储了标准字段)和表B(存储了自定义字段)。当用户对Account对象进行查询时,系统会将表A和表B进行联合,给出查询结果。为了避免联合操作,可以建立一个精简表C,其中同时存放了来自表A和表B的字段,它们都是用户需要经常使用和查询的。那么在用户对Account对象进行查询时,Salesforce直接对表C进行查询即可。
要注意的是,每一张精简表中的各个字段只能属于同一个对象,并且只能通过Salesforce的客服进行申请创建。
字段索引
为了优化各种查询语句,Salesforce内部使用了查询优化器。查询优化器中包括的最重要一点就是字段索引。在Salesforce中对很多字段都可以设置索引,或者自动被索引,比如Id、Name、CreatedById、CreatedDate,还有被设置为“唯一”(Unique)或“外部ID”(External ID)的字段。
在使用Salesforce的SOQL语言进行查询时,在WHERE部分尽量使用索引的字段,可以极大的提高查询效率。
有些字段的索引必须通过Salesforce的客服来启用。
记录所有者优化
Salesforce规定每条记录必须有所有者(Owner)。与此同时,Salesforce中对于数据记录的权限有着复杂的设定。每当数据记录的所有者的权限发生变化时,Salesforce会自动计算其所拥有的所有记录的权限。
在超大量数据的导入过程中,会产生很多数据,它们都需要被分配所有者。如果将大量记录统一分配到同一个用户作为所有者,而该用户在今后被更改了角色设定,那么所有属于该用户的记录都会被重新计算权限。记录的数量越大,计算所需的系统资源就会越大。
为了避免这种情况的发生,在进行导入数据的时候,需要尽量避免让同一个用户拥有过多的记录(10000条以内)。
如果某个用户必须成为很多记录的所有者,则尽量将此用户的角色定位为角色结构的顶端,并且尽量不要更改该用户的角色,这样可以避免非常多的权限重新计算。其他用户可以通过其他的共享设定来读取该用户拥有的数据记录。
对象的关系优化
Salesforce中可以对对象之间进行各种关系的定义,比如Lookup类型、Master-Detail类型等。当用户对于某条记录拥有权限,那么该用户对于此条记录的相关父记录也拥有权限。这些计算是Salesforce自动完成的。当某条数据记录拥有过多数量的相关子数据记录,而某条子记录被修改的时候,Salesforce有可能会执行相当多的计算量来检查各条数据记录的权限。
举个例子:
某条Account记录拥有100个Contact记录,Account记录的所有者不是用户A,而所有Contact记录的所有者都是A,那么A自动获得了该Account记录的权限。
当A将某条Contact记录的所有者改为用户B时,B同时得到了该Contact记录和Account记录的权限,而A则失去了该Contact记录的权限。
与此同时,Salesforce为了检查A是否还拥有Account记录的权限,会检查所有其他的99条Contact记录,只有当A失去了所有的Contact记录的权限后,A才会失去Account记录的权限。
从这个例子可以看出,当某条记录包含了太多的子记录时,更改某个子记录的权限会导致Salesforce对所有其他的记录进行一一检查,会耗费相当多的系统资源。
要解决这个问题,就要尽量避免某条父记录下拥有过多(10000条以上)的子记录。
精简对象相关设定
Salesforce中对于对象的共享权限、关系等设定有很多种。在进行数据导入时,Salesforce会根据这些设定对数据进行检测。当这些检测的数量过多的时候,会消耗相当多的系统资源。从以下几个方面可以进行优化:
- 组织默认共享权限(Organization-wide sharing defaults):当导入了一条记录时,如果该记录所属的对象有着默认的公开读写权限(Public Read/Write),那么系统会跳过对其权限的计算,减少了系统资源的使用。
- 对象关系:如果某对象和其他对象有着过多的“父-子”关系,那么当导入属于该对象的一条记录时,其相关的各种子记录的权限都会被检查。所以减少对象之间复杂的关系可以减少多余的检查,减少了系统资源的使用。
- 共享规则(Sharing rule):如果某对象被设定了很多的共享规则,在导入该对象的数据记录时,Salesforce会根据这些共享规则对其进行各种权限的检查,会消耗很多系统资源。
- 验证规则(Validation rule),触发器(trigger),工作流规则(Workflow rule):这些设定都会在数据导入时执行。当某对象拥有过多的这些设定,它们的执行会消耗非常多的系统资源。
数据导入的最佳实践
在导入数据前:
- 启用并行权限计算(parallel recalculation)和延迟共享计算(defer sharing calculation)功能:进行大量数据导入会导致非常长的共享规则计算。要避免这些问题,可以在数据导入的过程中将这些计算所消耗的系统资源减少。
- 建立角色结构定义
- 在导入数据之前导入用户。
- 尽可能的将对象的组织默认共享权限(Organization-wide sharing defaults)设定为公开读写权限(Public Read/Write),从而让系统跳过对这些对象的记录的权限计算。
- 让数据尽可能的“干净”,尤其是各种外键关系。如果有破坏了这些关系的数据存在,会在导入过程中跳出错误,延长导入的时间。
- 尽可能的停用数据相关的设定,比如验证规则(Validation rule),触发器(trigger),工作流规则(Workflow rule)。
在导入数据时:
- 如果对象之间有“父-子”关系,确保首先导入父对象,在导入子对象,确保导入的数据是“干净”的,不会出错的。
- 尽量使用insert和update的方式进行导入,而非upsert方式,因为后者需要更多的时间来完成操作。
- 当使用update方式进行数据导入,让导入的数据只包含更新的字段,而非对象的所有字段。
- Salesforce在更新子记录时,其所属的父记录会被锁定,直到子记录更新完成。在导入子记录时,尽量将从属于同一条父记录的子记录分成一组,从而在导入的过程中同一条父记录不会被不同的线程锁定。