当数据量遇上共享模型
另有 19 种语言版本
English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Українська · Español (México) · Français (Canada) · Deutsch (Schweiz)

第 3 个模块,共 4 个,属于 Data Architect 课程第 7 章为规模而设计。每个模块都可以单独阅读。 上一篇:热点:所有权、父记录和查找倾斜 · 下一篇:如果你今天不归档……
**本模块回答的问题:**一个尊重共享的模型,如何在大数据量下保持快速?
上一个模块找到了热点。现在加上安全,一个看起来合理的数据架构就在这里变得昂贵。900 万个工作订单是数据量问题。900 万个工作订单,每一个都恰好对正确的内部用户和正确的零售合作伙伴可见,就是一个大规模共享问题。一条记录不只是被存储;Salesforce 还必须回答**谁能看到它?**在规模上,这个答案就是数据架构的一部分。
共享也是数据
Section titled “共享也是数据 ”架构师计算数据量时,计算的是业务记录。但 Salesforce 还维护着支撑访问的东西:所有人、角色、组、共享规则、显式共享、成员关系。规模小的时候,你可以忘记这些工作的存在。规模大的时候,你忘不了。所以我从不说“共享的事以后让安全团队去处理”。我选择的关系、所有人、父记录、外部用户模型:每一样都影响共享。数据架构师和共享架构师可能是不同的人,但他们的架构是连在一起的。
The Share Table Has Its Own Number of Zeros
Section titled “The Share Table Has Its Own Number of Zeros”Chapter 3 introduced the share table: the share object behind each object, AccountShare for Account, Truck__Share for a custom Truck__c, where Salesforce keeps most of the sharing for a record, one row per grant: which record, who, how much and why (Understanding Sharing (在新标签页中打开); Sharing a Record Using Apex (在新标签页中打开)). It’s an object of its own, with its own rows, and at volume that’s exactly the point. The share table has its own Number of Zeros. ⟲
Salesforce describes three kinds of tables behind record access. The object record tables hold the records and who owns each one. The object sharing tables, the __Share objects, “store each access grant in separate rows called sharing rows, each of which grants a user or group access to a particular record.” And the group maintenance tables store who belongs to each group, and the access people inherit through roles and groups (Record-Level Access: Under the Hood (在新标签页中打开), Winter ‘27, archived copy (在新标签页中打开)). When we talked about recalculation, this is where the work happens: rows being added and removed in those tables. ⟲
So do the math for the share table the way we did it for the records. Say each of Steve Trucking’s 9 million work orders is shared by three sharing rules: to its Retail Partner’s users, to its distribution center’s managers, and to an operations region. Work Order’s share object is WorkOrderShare, “a sharing entry on a work order” (WorkOrderShare (在新标签页中打开)). That’s three of those rows per work order, about 27 million sharing rows behind 9 million records, before the owner’s own rows. Share the same records with individual users instead of groups, and the rows multiply by the number of people. The share table can be far bigger than the object it protects. ⟲
Step 1 of 3: the records. Nine million work orders. ⟲
Step 2 of 3: the share table, three rules to groups. ⟲
Step 3 of 3: the same access, shared person by person. Count the share table, not just the records. ⟲
That’s why the levers that keep sharing fast are mostly levers on the number of rows: ⟲
- Share with groups, not people. Salesforce’s own advice: grant access to the group instead of to the individuals, which “results in fewer sharing rows, thus reducing your organization’s record access data volume” (same source). ⟲
- A detail object has no share object at all. Its access comes from its master, so a master-detail child adds no sharing rows (chapter 3, and module 2’s Master-Detail at Volume for what that costs). ⟲
- High-volume community users don’t use sharing rows. They reach records through sharing sets instead, one of the reasons those licenses scale (chapter 3). ⟲
- Use a public default where the data isn’t confidential. A Public Read Only or Read/Write default needs no sharing rows to grant what everyone may already read (see Don’t Optimize Away Security, below). ⟲
Test knowledge. Know the share object (
AccountShare,Object__Share): one row per grant, with a row cause; the three kinds of tables behind record access (object record, object sharing, group maintenance); and that sharing with groups rather than individuals means fewer sharing rows. ⟲
从访问需求开始
Section titled “从访问需求开始 ”I don’t start with which sharing feature to use. I start with who needs access to what? For Steve Trucking, one requirement is clear: each Retail Partner sees its own deliveries, never another’s. Simple to say. At scale I immediately want to know how many partner users there are, how many deliveries, how a delivery relates to its partner, who owns the delivery, and what happens when a user changes roles, a partner user is added or removed, or a partner relationship changes, and how often any of that happens. The access requirement comes first; then a model that supports it at the zeros we expect. ⟲
Ownership Drives Access
Section titled “Ownership Drives Access”That’s why “who should own the delivery?” can’t be answered in isolation. If one integration user owns every work order, ingestion is easy, but if the business expected ownership to drive access, we’ve given up that way of controlling access. And if ownership doesn’t drive access, forcing millions of records through complicated ownership assignments adds complexity for nothing. So my rule for machine-created records applies here too: does ownership matter for sharing? If it does, ownership should reflect the access model. If it doesn’t, we have more freedom. One decision, made by the data architect and the sharing architect together. ⟲
角色层级不是组织架构图
Section titled “角色层级不是组织架构图 ”团队设计角色层级时,常常照搬组织架构图。然后公司重组,有人挪动了一个角色,Salesforce 就得算出访问上的后果。规模小时没人注意。在几百万条记录上,重组就是一次大型数据操作。所以对拥有大量记录的所有人,指导是不给角色,或者在层级顶部给一个独立、稳定的角色(Ownership Data Skew (在新标签页中打开))。这个原则可以推广:**在规模上,稳定性是一项设计特性。**挂在一个共享结构上的记录越多,改动它时就要越小心。
组也一样。公共组为共享规则提供来源;用户属于组;组里包含组。这些是有用的工具,但如果大量用户和记录依赖不断变化的组成员关系,你就需要理解重新计算。所以拥有大量记录的所有人要不进入用作共享规则来源的公共组(同一来源)。教训不是“公共组不好”。而是:不要不假思索地把你最大的记录集中点,连到你最易变的访问结构上。
共享重新计算是真实的工作
Section titled “共享重新计算是真实的工作 ”Steve Trucking 改变了运营模式:几百个用户调动,所有权变化,角色和组变化,一条大的共享规则也变了。这听起来像配置。但平台可能要对一大批记录重新计算访问权限,所以我把它当作一次数据操作。多少用户、多少记录、多少所有权和成员关系的变化?要重新计算多少?能在真实数据量下测试吗?什么时候运行,期间用户看到什么?一次大型安全调整,值得和一次大型数据迁移同样的纪律。
And don’t recalculate everything after every change. Making one change, waiting for everything to recalculate, then the next, then the next, rebuilds access over and over while the design is still moving. Salesforce’s answer for large realignments is deferred sharing calculations: prepare all the role, group and sharing-rule changes, apply them in a negotiated maintenance window, and let the recalculation run once (Deferred Sharing Maintenance (在新标签页中打开)). Change, change, change, recalculate once. Two more of Salesforce’s suggestions keep the work down: process role hierarchy changes from the bottom (leaf) nodes up, “to avoid duplicate processing,” and remove redundant paths of access, “such as sharing rules that provide access to people who already have it through the hierarchy” (Designing Record Access for Enterprise Scale (在新标签页中打开), Winter ‘27). ⟲
Test knowledge. Know the tools for large access changes: deferred sharing calculations (prepare every change, apply them in an agreed maintenance window modeled in a full copy sandbox, recalculate once) and granular locking, on by default, which lets unrelated role and group operations run at the same time. ⟲
At scale, access realignment is a data operation. ⟲
“推迟”不等于随意。如果一个变化大到需要推迟共享计算,我就要一个计划:在真实数据量下测试过,有业务认可的维护窗口,有验证,有没跑完时的后备方案,还要了解期间用户会体验到什么。Salesforce 的指导是先在完整副本沙盒里建模(同一来源),因为一个在 5,000 条测试记录上运作得很漂亮的安全模型,对 5,000 万条记录什么也证明不了。测试你真正要设计的“零的个数”。
细粒度锁定有帮助,但不是解药
Section titled “细粒度锁定有帮助,但不是解药 ”Role and group updates lock the group-membership tables while they run, which used to make unrelated sharing operations collide. Granular locking, now on by default, lets unrelated group operations run at the same time (Group Membership Locking (在新标签页中打开)); retry logic, serial processing, and scheduling separate group maintenance jobs so they don’t overlap help with what’s left. The idea is worth remembering: don’t lock more of the access structure than the operation needs. But don’t conclude “locking is solved.” Granular locking reduces some contention. It doesn’t rescue a poor ownership model, a volatile hierarchy, or an access design that constantly forces massive recalculation. Platform features help; architecture still matters. ⟲
Steve Trucking:大规模的合作伙伴隔离
Section titled “Steve Trucking:大规模的合作伙伴隔离 ”在检查点 1,每个工作订单都持久地带着它的零售合作伙伴,因为合作伙伴隔离是一项需求。规模数字让这一点更重要,而不是更不重要:如果 Redrock 占业务的 40%,五年下来就是大约 360 万个 Redrock 工作订单。这个关系是对的;Redrock 确实是一个合作伙伴。所以访问设计必须遵循真实的业务关系(合作伙伴用户看到自己合作伙伴的工作订单,配送中心经理只看到自己配送中心的),而不是扭曲模型。上一个模块里“每个配送中心一个子客户”的结构在这里帮了两次忙:它分散了子记录,也让配送中心级别的访问有一个真实的东西可以挂靠。
And keep authorization separate from identity. At the checkpoint we decided not to unify Recipients across partners, precisely because a shared identity is exactly the kind of link that can expose one partner’s data to another. Even where identity resolution is used inside one partner, it answers who might this person be? Sharing answers who may see this record? Blur them, and at this scale the mistake isn’t wrong once. It’s wrong millions of times. ⟲
内部访问又是另一回事
Section titled “内部访问又是另一回事 ”Partners are only part of it. Coordinators, crews, care agents, operations, finance and sales need different things. A care agent may need broad visibility to answer “where’s my delivery?”; a crew only today’s stops, and the Recipient’s details only on the day; operations a region; finance the money, not every operational detail; sales the partner, not the Recipients. The Sharing and Visibility course goes through Steve’s 25 Ways to Share a Record; I won’t reproduce it here. The data architect’s job is to recognize that the model either enables those choices or constrains them. ⟲
有时安全应该改变模型。当两类信息的所有人、生命周期、受众或共享需求完全不同时,你可以在一条记录上堆砌字段级控制,也可以把数据拆分到一个有自己边界的独立对象里。我不会只为了不配置字段级安全就拆分,但安全是改变物理模型的正当理由。
共享有它自己的“零的个数”
Section titled “共享有它自己的“零的个数” ”两个设计,各有 1,000 万条记录:一个所有权简单、层级稳定、共享规则少、成员关系变动小;另一个所有权高度分散、角色频繁变化、嵌套的大组、大量共享规则、不断重组。记录数相同,规模问题却完全不同。所以对每一个大数据量对象,我也要访问模型的数字:有多少所有人、集中程度如何、默认访问权限、哪些层级关系、规则和组起作用、有多少外部用户,以及有人换角色、新增合作伙伴、重组一个区域时会发生什么。然后问一个问题:**这个设计可能引发的最大一次重新计算是什么?**这就是我要测试的场景。
Count the access model, not just the records. ⟲
不要为了优化而丢掉安全
Section titled “不要为了优化而丢掉安全 ”There’s a dangerous conclusion to avoid: sharing is expensive, so make everything public. No. Performance isn’t an excuse to abandon a security requirement. Salesforce’s own guidance draws the line in the right place: “Use a Public Read Only or Read/Write organization-wide default sharing model for all non-confidential data” (same guide). Non-confidential data can be public; confidential data stays protected, and the design has to carry it. The job is an architecture that satisfies both: simpler ownership, more stable hierarchies, better group design, splitting data with different security needs, different relationships, planned realignments. “Private is slower, so make it public” is not an architecture strategy. ⟲
**考试之外:AI 改变了什么。**智能体检索和汇总的速度比任何人都快,这让过于宽泛的访问模型更加危险。不要依赖一句提示词说“不要把 Brightwave 的数据给 Redrock 看”。边界属于架构:应该由授权限制智能体能触及什么,而不是由指令限制它选择透露什么。让授权模型随数据模型一起扩展。
架构师在这里决定什么
Section titled “架构师在这里决定什么 ”- 对每个大数据量对象,哪些关系、所有人、角色、组和共享规则驱动访问。
- 拥有大量记录的所有人和其他热点,是否与易变的层级和组结构隔离。
- 大型访问调整如何测试、安排、只重新计算一次,并在生产数据量下验证。
- 不同的安全需求是否足以支持拆分数据,而不是让对一条记录的访问变得复杂。
- 合作伙伴、员工、应用和智能体的访问,如何始终与业务关系挂钩,而不是走身份的捷径。
为 1,000 条记录画一个安全的设计很容易,画一个人人都能看到一切的快速设计也很容易。架构师的工作是让两者都能存活的系统:正确的人看到正确的数据,加上那些零以后仍然运作。在规模上,共享是数据架构的一部分。
- Object Reference for the Salesforce Platform, WorkOrderShare (在新标签页中打开) (Winter ‘27), checked 2026-11-01. ⟲
- Salesforce Developers, Designing Record Access for Enterprise Scale, Takeaway: Tuning Group Membership for Performance (在新标签页中打开) (Winter ‘27): leaf-first hierarchy changes and removing redundant access paths, checked 2026-11-01. ⟲
- Salesforce Developers, Designing Record Access for Enterprise Scale (Winter ‘27): Ownership Data Skew (在新标签页中打开), Group Membership Locking (在新标签页中打开) and Deferred Sharing Maintenance (在新标签页中打开), checked 2026-11-01. ⟲
- 深入阅读:Sharing and Visibility Architect 课程的大规模共享 (coming soon)。
- SteveTechArc, Salesforce Documents by Release: these guides, once a year from Winter ‘16, each with an archived copy. ⟲
- Salesforce, Record-Level Access: Under the Hood (在新标签页中打开) (Winter ‘27, archived copy (在新标签页中打开)), checked 2026-10-20. ⟲
- Apex Developer Guide, Understanding Sharing (在新标签页中打开) and Sharing a Record Using Apex (在新标签页中打开), checked 2026-11-01. ⟲
