所有、親、参照のスキュー
ほかに 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)

モジュール2/4:Data Architectコース第7章「大規模に向けた設計」。各モジュールは単独でも読めます。 前へ:量がすべてを変えるとき · 次へ:量が共有モデルとぶつかるとき
このモジュールが答える問い: あまりに多くのレコードが一つのものを指すと、何が起きるのか?
大量データの問題は、いつもレコードが多すぎることだとは限りません。同じもの、つまり一人の所有者、一つの取引先、一つの親、一つの参照値に、あまりに多くのレコードがつながっていることが問題になる場合もあります。交通を考えてみてください。都市には何百万台もの車があっても、ちゃんと機能します。困るのは、全員が午後5時に同じ高速道路の出口に向かうときです。総数も重要ですが、集中も重要です。私はこうした集中をホットスポットと呼び、Salesforceはデータスキューと呼びます。いくつかの種類がありますが、その根っこにある考えは一つです。モデルの一点にあまりに多くの活動が集まること。
親子のスキュー
Section titled “親子のスキュー ”The easiest to picture. One account with 100 contacts: nothing unusual. A thousand: probably fine. Ten thousand: now I’m paying attention. My design rule is no more than about 10,000 children under one parent, and Salesforce’s guidance draws the same line: “a large number of child records (10,000 or more) with a single parent account” is a common cause of poor performance (Parent-Child Data Skew (新しいタブで開きます)). Salesforce’s own example shows why. Put 300,000 contacts under one account. A user who can see one of those contacts gets implicit access to the account. When that user loses access to the contact, Salesforce has to check the other 299,999 contacts before it can decide whether to remove the user’s access to the account. Do that for many users at once, and it gets expensive. Salesforce also names one way to take part of that cost away: where your security requirements allow, set the child object to Controlled by Parent, so there are no parent implicit shares to maintain (same source). In practice, it’s the most common skew I see, and I’ve seen users notice visible lag at around 20,000 children under one parent. Where somebody feels it depends on what the system is doing. That’s why 10,000 is a design threshold, not a promise that record 10,001 breaks anything. The real question is: why are all these records pointing at the same parent? ⟲
Step 1 of 2: every line points at one account. That’s the hot spot. ⟲
「未割り当て」の取引先と、取引先プール
Section titled “「未割り当て」の取引先と、取引先プール ”The classic case is contacts with no real account. Somebody decides every contact needs an account, so they create Unassigned Contacts and put every contact without an account there. Problem solved, until there are 300,000 contacts under it. We created an artificial hot spot because the model required us to put everything somewhere, and the relationship doesn’t even carry business meaning. It worked beautifully at 500 records. Then the Number of Zeros caught up with it. ⟲
What do you do when you’ve got a million contacts under it? I’ve seen child accounts by state, one unhandled-contacts account per state. I’ve seen an automatic version: whenever an account reaches 10,000, create another one. It can be a little awkward, but it spreads the load. ⟲
One answer is an account pool: Unassigned Contacts 001, 002, 003 and so on, with the children spread across them, each kept under the threshold. It works, and it’s Salesforce’s own advice: “Distribute child records so that no parent has more than 10,000 child records,” and for contacts without real accounts, “set up several dummy accounts and distribute the contacts among them” (Best Practices for Deployments with Large Data Volumes: General (新しいタブで開きます), Winter ‘27). But those aren’t real accounts; they’re architecture artifacts. Users will ask who “Unassigned Contacts 017” is and why it’s in their search results. So when I use a pool, I hide the placeholder parents from normal business experiences as much as I can. It’s a recurring trade-off: sometimes scale forces a structure that exists for the platform, not the business. When it does, don’t pretend it’s business data. Name it, document it, hide it where appropriate. ⟲
Step 2 of 2: the same contacts, spread across a pool. Nothing moved but where they point. ⟲
Master-Detail at Volume
Section titled “Master-Detail at Volume”Contacts under an account are a lookup. Master-detail is a different decision, and it’s one you make in the data model, long before the records arrive. Here’s the question I ask in class: would an invoice ever have more than 10,000 line items? No, it never would. So an invoice and its lines can be master-detail all day long. Now ask the same question of every master-detail relationship you’re about to build: at the volume we expect, will one parent ever pass 10,000 children? ⟲
Salesforce draws the same line: “As a best practice, don’t exceed 10,000 child records for a master-detail relationship” (オブジェクトリレーションの考慮事項 (新しいタブで開きます)). Master-detail is the strongest relationship Salesforce gives you, and that’s exactly why the number matters. The detail record has no owner of its own; its access is controlled by the parent. Delete the parent, and every child goes with it. A child can’t move to another parent unless you allowed reparenting. Roll-up summaries on the parent have to keep up as the children change. And saving a child can lock the parent, which is why Salesforce’s loading advice is to group child records by their parent “to minimize locking conflicts” (Loading Data from the API (新しいタブで開きます)). With ten children, none of that is noticeable. With a hundred thousand, every one of them is. ⟲
It’s also hard to undo. A master-detail relationship can only be converted to a lookup when the parent has no roll-up summary fields, and converting it changes the child’s sharing to Public Read/Write (same source). By the time volume tells you it was the wrong choice, the relationship may be holding up reports, sharing and automation. Count the children before you choose the relationship. ⟲
Steve Trucking has one of these decisions in its model. Each Retail Partner sends a Manifest (Manifest__c, a custom object) for each distribution center, for each working day. Manifest is custom, so master-detail to the partner’s account is allowed, and it’s tempting: the manifest would inherit the partner’s sharing, which is exactly the isolation we want. Now count. Our largest partner has nine or more DCs: nine manifests a working day, about 2,700 a year. Past 10,000 in under four years, under one parent, and every manifest revised on the day, so every revision would touch the partner’s account. That’s why the model makes Manifest a lookup and handles partner access through sharing. The invoice stays small; the manifests keep coming. ⟲
Step 1 of 2: master-detail, where the parent stays small. ⟲
Step 2 of 2: a lookup, where the children keep coming. ⟲
Watch Account with its contacts and opportunities too. It isn’t master-detail, but it behaves like a pseudo master-detail, with implicit sharing to the parent, which is why the 10,000 guidance shows up there as well. None of this means never use master-detail at scale. It means don’t choose a strongly coupled relationship and then act surprised that the records are strongly coupled. ⟲
Test knowledge. Know the 10,000-children guidance for master-detail, and what master-detail brings with it at volume: no owner on the detail (access controlled by the parent), cascade delete, no reparenting unless allowed, roll-up summaries, and parent locking when children are saved. Converting to a lookup needs no roll-up summaries on the master. ⟲
所有のスキュー
Section titled “所有のスキュー ”Now the owner. I ask the room: who owns a million records? The admin? Is the admin sitting there creating a million records? Usually it’s the integration user or the data load user. The records come in, and nobody knows who to give them to. We create an integration user, it creates records, nobody thinks about ownership (“it’s just the integration user”), and a year later that user owns 2 million records. Salesforce calls it ownership data skew when one user owns more than 10,000 records of an object, and the classic example is all the unassigned leads parked on a dummy user (Ownership Data Skew (新しいタブで開きます)). That doesn’t mean a user can never own more. It means understanding the consequences: ownership isn’t a Created By stamp. It drives the role hierarchy, sharing rules and recalculation: behind the scenes, Salesforce keeps share records for the owner’s records above them in the role hierarchy. Attach millions of records to one owner who sits deep in the sharing model, and changing anything about that owner gets expensive. ⟲
The guidance matches what I teach in class. If a few users must own a very large number of records, give them no role; if they need one, put them in a separate role at the top of the hierarchy and don’t move them, and keep them out of public groups used as sources for sharing rules (same source). One catch with the top role: that user inherits access to all the data owned by or shared with the users below them. You could spread the records across a bunch of users instead, but for an integration user or a data load user, that typically isn’t worth the trouble. ⟲
We’re isolating the hot spot from the structures that trigger recalculation. Imagine a user who owns 5 million records being moved in a reorganization. That isn’t moving a box on the org chart; Salesforce may have to re-evaluate access across 5 million records. At this scale, organizational changes become data operations. ⟲
Test knowledge. Know the skew thresholds and the fixes: ownership skew when one user owns more than 10,000 records of an object (no role, or a separate role at the top that doesn’t move, and out of public groups used by sharing rules); parent-child skew at about 10,000 children under one parent. ⟲
機械が作成したレコードは誰が所有すべきか?
Section titled “機械が作成したレコードは誰が所有すべきか? ”誰がレコードを作成したかと、誰がそれを所有するかは、同じ問いではありません。RedrockがAPIを通じて50万件の配送を送り、統合ユーザーがそれを作成します。統合ユーザーがそれをずっと所有すべきでしょうか? そうかもしれませんが、作成したからという理由だけではいけません。そして今では、エージェントもレコードを作成します。
私の立場はこうです。**所有が共有にとって重要かどうかによる。**統合ユーザーやエージェントのユーザーは正当なユーザーであり、レコードを所有できます。そのオブジェクトで所有がアクセスを決めている(ロール階層や共有ルールを通じて)なら、ビジネスが求める所有者、つまり実在のユーザー、オブジェクトが対応していればキュー、あるいは専用の所有者ユーザーにレコードを割り当てましょう。所有がアクセスを決めていないなら、エージェントや統合ユーザーを所有者のままにするほうが良い選択かもしれません。監査証跡が、そのレコードを作成したものにまっすぐたどれるからです。いずれにせよ、ふつうレコードは人が所有するからといって機械が作成したレコードを機械的に割り当て直すのではなく、このオブジェクトにとって所有者が何を意味するかを決めましょう。そして「作成者」は残っていることを忘れないでください。所有を割り当て直しても、統合が作成したという事実は失われません。作成者と所有者は別の問いに答えます。一つの項目に両方を答えさせると、悪いモデルになります。
参照のスキュー
Section titled “参照のスキュー ”A lookup can be a hot spot too: millions of records pointing at the same location, category, reference record or configuration record. Salesforce’s own training defines it: “Lookup skew happens when a very large number of records are associated with a single record in the lookup object” (Large Data Volumes: Design Your Data Model (新しいタブで開きます)). The danger isn’t “lots of lookups.” It’s concentration combined with activity: if millions of active records reference one record, and transactions keep touching that relationship, operations start colliding over it. That’s record locking, which chapter 11 covers. For now, recognize the shape: many active records, one heavily referenced record, worth inspecting. ⟲
すべてのスキューが同じように危険なわけではない
Section titled “すべてのスキューが同じように危険なわけではない ”「1万件 = 悪い」と暗記しないでください。決して変わらない参照値を指す5万件の履歴レコードで、共有での役割もなく、同時の活動もほとんどないなら、問題ないかもしれません。頻繁に変わり、共有を決め、積み上げ集計を担い、複数の統合から同時に叩かれる親の下にある2万件の現役のレコードは、まったく別の話です。量には形があり、スキューにも形があります。そこにどれだけのレコードが集まるのか? どれだけ頻繁に変わるのか? 親は変わるのか? そのリレーションは共有やロックを決めるのか? 統合が子を同時に更新するのか? 所有者や親を動かすと再計算が起きるのか? 数字はどこを見るべきかを教えてくれ、振る舞いはどれだけ心配すべきかを教えてくれます。
Steve Trucking:ホットスポットはどこか?
Section titled “Steve Trucking:ホットスポットはどこか? ”5年後には約900万件の作業指示を見込みました。誰かが「すべての配送を統合ユーザーに所有させよう」と言ったとします。900万件のレコードに、所有者が1人。配送の共有にとって所有は重要でしょうか? 重要でないなら、上で述べたようにロール階層や共有ルールのグループから切り離した専用の所有者が機能し得ます。重要なら、統合ユーザー1人を所有者にするのはビジネスモデルとして間違いです。統合はレコードを作成しますが、だからといってそれを所有すべきだということにはなりません。
Then the Retail Partner. Every work order carries its partner, deliberately, because partner isolation matters. But if one partner is 40% of the business, five years of deliveries is about 3.6 million work orders under one partner account. Does that make the relationship wrong? No. The business relationship is real, and I’m not going to invent 400 fake Redrock accounts because I don’t like the count. But I am going to look for a split the business would recognize. Each partner has real distribution centers, so a child account per DC under the partner spreads the work orders nine or more ways while every account still means something. Add archiving completed deliveries after the claims window, and the active children per parent stay low. ⟲
これが2つの解決策の違いです。「未割り当ての取引先責任者」はもともと人工的なものだったので、プールに分けても意味は失われません。Redrockは本物のパートナーです。Redrock 001、002、003に分ければモデルが壊れます。本物の物流センターに分けるなら壊れません。**規模のための解決策も、意味を保たなければなりません。**答えが別のリレーション、共有戦略、クエリのパターン、ストレージのモデル、アーカイブのポリシーになることはあっても、本物のビジネスエンティティに偽物の身元を与えることには決してなりません。
Inspect, not bad. Concentration matters, not the total. ⟲
図の上でホットスポットを見つける
Section titled “図の上でホットスポットを見つける ”私の好きな演習があります。データモデルを取り出して、オブジェクトだけでなく矢印を見てください。それぞれのリレーションについて尋ねます。**この矢印のこちら側に、どれだけのレコードが積み重なり得るか?**次に所有者について同じことを尋ねます。そして3年後、5年後、10年後を想像します。レコードはどこに集中するでしょうか? 明日の問題は、たいていそこに隠れています。
試験の先へ:AIが変えること。 人は1日に20件のレコードを作るかもしれませんが、エージェントは数千件作れます。エージェントに専用のユーザーを与え、すべてのレコードをそのまま所有させれば、所有のスキューは人の場合よりはるかに速く現れます。エージェントが所有すること自体は間違いではありません。でも、量が既定の設定をアーキテクチャの一部にしてしまう前に、エージェントが作成したレコードにとって所有者が何を意味するかを決めておきましょう。
ここでアーキテクトが決めること
Section titled “ここでアーキテクトが決めること ”- 親子、所有、参照のリレーションがどこにレコードを集中させ、それがホットスポットになるほど活発かどうか。
- 機械が作成したレコードを統合ユーザーやエージェントのユーザーが所有し続けるのか、所有がアクセスを決めるので割り当て直すのか。
- 大量のレコードを所有するユーザーを、ロール階層や共有ルールのグループからどう切り離すか。
- 人工的な親をいつプールに分けてよいのか、そして本物のリレーションにはいつ意味のある分割が必要なのか。
- Whether each master-detail relationship stays under about 10,000 children per parent at projected volume, or should be a lookup. ⟲
何千もの所有者と親に分散した100万件のレコードは、一か所を指す100万件のレコードとはまったく違う振る舞いをします。ホットスポットは早めに探しましょう。所有者、親、参照、ゼロの数が集まるあらゆる場所です。目標は大きなリレーションをすべてなくすことではありません。正しくビジネスを表しているものもあります。目標は、高速道路を開通させる前に交通がどこに向かうかを知ることです。何百万件ものレコードが同じ出口に向かい始めてからでは、道路を変えるのははるかに難しくなります。
さらに学ぶ
Section titled “さらに学ぶ ”- Salesforce Developers, Best Practices for Deployments with Large Data Volumes, Loading Data from the API (新しいタブで開きます) (Winter ‘27): group child records by parent to minimize locking conflicts, checked 2026-11-01. ⟲
- Salesforce Help, オブジェクトリレーションの考慮事項 (新しいタブで開きます): no more than 10,000 child records for a master-detail relationship; converting master-detail to lookup, checked 2026-11-01. ⟲
- Salesforce Developers, Designing Record Access for Enterprise Scale (Winter ‘27): Ownership Data Skew (新しいタブで開きます) and Parent-Child Data Skew (新しいタブで開きます), checked 2026-11-01. ⟲
- Salesforce Developers, Best Practices for Deployments with Large Data Volumes: General (新しいタブで開きます) (Winter ‘27), the 10,000-record owner and parent guidance, checked 2026-11-01. ⟲
- Trailhead, Large Data Volumes: Design Your Data Model (新しいタブで開きます): parent-child, ownership and lookup skew, checked 2026-11-01. ⟲
- Salesforce engineering blog, Managing Lookup Skew to Avoid Record Lock Exceptions (新しいタブで開きます) (2013; older, but still the clearest explanation; checked 2026-11-01). ⟲
- SteveTechArc, Salesforce Documents by Release: these guides, once a year from Winter ‘16, each with an archived copy. ⟲
