盘点Salesforce Big Object

为拓展sf标准字段历史跟踪限制,选用Big Object存储Change Logs。介绍了使用Big Object的关键要点,如数据存储量、索引设置等。还说明了部署Big Object的步骤,包括准备文件、使用工具部署等。此外,探讨了批量删除数据时不同索引排序的表现及应对方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景介绍】:为了拓展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 -> 放在文件根节点

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>PermissionSet</name>
    </types>
    <version>39.0</version>
</Package>

ListingChangeLog__b.object -> 你可以定义字段并设置索引及排序

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <deploymentStatus>Deployed</deploymentStatus>
    <description>This big object will be used in tracking fileds change logs.</description>
    <fields>
        <fullName>ChangedBy__c</fullName>
        <description>This would be used to record who change the field value. Mainly designed for historical data import.</description>
        <externalId>false</externalId>
        <label>ChangedBy</label>
        <referenceTo>User</referenceTo>
        <relationshipName>ListingChangeLogs</relationshipName>
        <required>false</required>
        <type>Lookup</type>
    </fields>
    <fields>
        <fullName>ChangedTime__c</fullName>
        <description>Add index to datetime for quering purpose.</description>
        <externalId>false</externalId>
        <label>ChangedTime</label>
        <required>true</required>
        <type>DateTime</type>
    </fields>
    <fields>
        <fullName>Field__c</fullName>
        <description>Store field api name. For imported logs, we will also record the fields, such as created, contactcreatedfromlead, locked, unlocked and owner etc.</description>
        <externalId>false</externalId>
        <label>Field</label>
        <length>30</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>IsDeleted__c</fullName>
        <description>Defualt value is &apos;0&apos;.
When a record was deleted, we would mark the field as &apos;1&apos;, then delete inactive logs using apex batch when a records were deleted exceed 15d.</description>
        <externalId>false</externalId>
        <label>IsDeleted</label>
        <length>1</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>IsImported__c</fullName>
        <description>Defualt value is null.
When a record was imported, we would mark the field as &apos;1&apos;.</description>
        <externalId>false</externalId>
        <label>IsImported</label>
        <length>255</length>
        <required>false</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>NewValue__c</fullName>
        <description>Default we won&apos;t record the long text area exceed 255 characters.</description>
        <externalId>false</externalId>
        <label>NewValue</label>
        <length>131072</length>
        <type>LongTextArea</type>
        <visibleLines>3</visibleLines>
    </fields>
    <fields>
        <fullName>OldValue__c</fullName>
        <description>Default we won&apos;t record the long text area exceed 255 characters.</description>
        <externalId>false</externalId>
        <label>OldValue</label>
        <length>131072</length>
        <type>LongTextArea</type>
        <visibleLines>3</visibleLines>
    </fields>
    <fields>
        <fullName>ParentId__c</fullName>
        <description>We will use the field to associate logs with any objects need to be tracked.</description>
        <externalId>false</externalId>
        <label>ParentId</label>
        <length>18</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>SobjectType__c</fullName>
        <description>Store sobject api name.</description>
        <externalId>false</externalId>
        <label>SobjectType</label>
        <length>28</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <indexes>
        <fullName>LogIndex</fullName>
        <fields>
            <name>IsDeleted__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
        <fields>
            <name>SobjectType__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
        <fields>
            <name>ParentId__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
        <fields>
            <name>ChangedTime__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
        <fields>
            <name>Field__c</name>
            <sortDirection>ASC</sortDirection>
        </fields>
    </indexes>
    <label>Listing Change Log</label>
    <pluralLabel>Listing Change Logs</pluralLabel>
</CustomObject>

Change_Logs_Listing_BigObject.permissionset -> 设置字段的读写权限
注意:权限设置要剔除索引字段(索引字段必填,必填字段默认读写都勾上)。

<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
  <label>Listing Change Logs Permission Set</label>
    <fieldPermissions>
      <editable>true</editable>
      <field>ListingChangeLog__b.ChangedBy__c</field>
      <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
      <editable>true</editable>
      <field>ListingChangeLog__b.IsImported__c</field>
      <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
      <editable>true</editable>
      <field>ListingChangeLog__b.NewValue__c</field>
      <readable>true</readable>
    </fieldPermissions>
    <fieldPermissions>
      <editable>true</editable>
      <field>ListingChangeLog__b.OldValue__c</field>
      <readable>true</readable>
    </fieldPermissions>
</PermissionSet>

打包成zip文件注意事项:全选文件 -> 右键 -> 发送到 -> 压缩zipped文件夹,或全选+添加压缩文件zip,如过直接将所有文件放入一个主文件,再压缩,部署会失败。


b. 使用Workbench工具部署元数据文件:


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__cf2__c
1A
2B




 

导入后如下:
asc类型:f1,f2同升序


desc类型:f1,f2同降序


mix类型:f1升序,f2降序

step3: 测试Code及删除效果比较:

List<test_asc__b> ascTests = [select f1__c, f2__c from test_asc__b];
Database.deleteImmediate(ascTests);

asc类型2条记录成功删除;
desc / mix删除时报错如下:


如果加了limit 1,则能成功删除:

List<test_desc__b> 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,转到抽象类里面做排序也行。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值