【背景介绍】:为了拓展sf标准字段历史跟踪18个月的保质期(从标准页面访问),和超期后额外6个月的API/Data Loader访问的限制(共计2年),同时为扩展标准Tracking20个字段的限制以及满足客户对部分长文本值变更监控的需求,在节省费用的前提下,选用了使用Big Object来存储Change Logs。
【影响决策的关键Points】:幕布笔记
1. 每个对象最多存10亿条数据;
Big objects provide consistent performance for a billion records or more, and are accessible with a standard set of APIs to your org or external system.
2. 每个对象必须有一个加索引的字段,且必填;
3. 一个对象最多加5个索引,字段值的长度不能超过100个字符;
4. 一旦加索引,SOQL的WHERE语句不能加非索引字段为过滤条件,同时必须要个遵从索引顺序做过滤,且不能隔行;
如:索引字段为f1__c, f2__c, f3__c,如果要加2个条件,不能是f1__c + f3__c的组合,也不能是f2__c + f3__c的组合,只能为f1__c + f2__c组合,称为No Gap.
5. 索引字段一旦加了排序,如ASC/DESC,SOQL的排序中不能更改;
6. 自身对象不能加Tirgger,其他对象的Trigger中新建该对象记录需使用异步方法;
7、如果所有索引字段值拼起来的字符串相同,insert操作会视为update;
如:22条数据在使用Salesforce Inspector做导入操作时,最终保留20条,稍后的记录会覆盖前面的记录。
【常见问题及核心解决要点】:
01. 如何部署Big Object,步骤及成功关键因素?
我们可以通过Setup页面去创建Big Object,并为字段加索引,一旦创建完你会意识到2点问题:
其一,如何将状态变为Deployed,而不是In Development;
其二,如何调整字段数据类型和重新配置索引;
这两点可能都会让你在反复设计表结构,考虑实施过程中需要用到soql的所有场景,但最终会将你引致最佳实践 —— 配置元数据文件,部署元数据。
【最佳实践步骤】:
a. 你需要准备3个文件,并放进正确的目录下:
模板文件:
package.xml -> 放在文件根节点
*
CustomObject
*
PermissionSet
39.0
ListingChangeLog__b.object -> 你可以定义字段并设置索引及排序
Deployed
This big object will be used in tracking fileds change logs.
ChangedBy__c
This would be used to record who change the field value. Mainly designed for historical data import.
false
User
ListingChangeLogs
false
Lookup
ChangedTime__c
Add index to datetime for quering purpose.
false
true
DateTime
Field__c
Store field api name. For imported logs, we will also record the fields, such as created, contactcreatedfromlead, locked, unlocked and owner etc.
false
30
true
Text
false
IsDeleted__c
Defualt value is '0'.
When a record was deleted, we would mark the field as '1', then delete inactive logs using apex batch when a records were deleted exceed 15d.
false
1
true
Text
false
IsImported__c
Defualt value is null.
When a record was imported, we would mark the field as '1'.
false
255
false
Text
false
NewValue__c
Default we won't record the long text area exceed 255 characters.
false
131072
LongTextArea
3
OldValue__c
Default we won't record the long text area exceed 255 characters.
false
131072
LongTextArea
3
ParentId__c
We will use the field to associate logs with any objects need to be tracked.
false
18
true
Text
false
SobjectType__c
Store sobject api name.
false
28
true
Text
false
LogIndex
IsDeleted__c
ASC
SobjectType__c
ASC
ParentId__c
ASC
ChangedTime__c
ASC
Field__c
ASC
Listing Change Logs
Change_Logs_Listing_BigObject.permissionset -> 设置字段的读写权限
注意:权限设置要剔除索引字段(索引字段必填,必填字段默认读写都勾上)。
true
ListingChangeLog__b.ChangedBy__c
true
true
ListingChangeLog__b.IsImported__c
true
true
ListingChangeLog__b.NewValue__c
true
true
ListingChangeLog__b.OldValue__c
true
打包成zip文件注意事项:全选文件 -> 右键 -> 发送到 -> 压缩zipped文件夹,或全选+添加压缩文件zip,如过直接将所有文件放入一个主文件,再压缩,部署会失败。
c. 为需要访问权限的用户添加Permission Set;
Tip:如果为了避免后续添加新用户忘记加permission set,可以去对象上为profile增加FLS.
当然假如你忘记加权限也没关系,因为你导入数据的时候,它也会提醒你:
DONE...
2. 如何批量删数据 —— 如何巧妙的入坑进一步探索Big Object的奥秘?
这里有些小伙伴在小试牛刀的时候会一步定乾坤,还有些像我这样的,习惯性入坑选手就得好好折腾一番了。
不妨先抛个结论:如果Index里面存在DESC,那么使用Database.deleteImmediate批量删除数据时,只能加LIMIT 1来挨个挨个删;否则,如果都为ASC,想咋删就咋删!!!
在探索这个潜在问题时,不妨穷尽如下可能性:
a. 当索引都是asc;
b. 当索引都是desc;
c. 当索引包含desc这种mix类型;
目标:探索批删数据表现
step1: 新建如下3中Big Object对象,且字段都为加索引的f1__c / f2__c;
step2: 导入相同数据:
f1__c | f2__c |
1 | A |
2 | B |
导入后如下:
asc类型:f1,f2同升序
desc类型:f1,f2同降序
mix类型:f1升序,f2降序
step3: 测试Code及删除效果比较:
List ascTests = [select f1__c, f2__c from test_asc__b];
Database.deleteImmediate(ascTests);
asc类型2条记录成功删除;
desc / mix删除时报错如下:
如果加了limit 1,则能成功删除:
List descTests = [select f1__c, f2__c from test_desc__b limit 1];
Database.deleteImmediate(descTests);
注意:如果desc / mix均只有一条数据,不加LIMIT 1也能成功删除。
【结论】:在使用Big Object的时候最好加Index的字段都设计成ASC,以防重复问题1的操作。如果确实需要DESC,转到抽象类里面做排序也行。