Pegaデータクラスのキー設計|業務キーと代替キー(GUID)の選択と一意性担保
キー設計はデータモデルの土台であり、後から直すコストが最も高い箇所です。人間可読な業務キーと安定した代替キー、どちらを主キーにするかで参照の壊れやすさが変わります。本記事では一意性の担保手段と、可変値をキーにしてしまう典型的な失敗の回避を扱います。
結論から:可変値はキーにしない。変わりうるなら代替(サロゲート)キー
Pega でデータクラスを設計するとき、避けて通れないのが「このクラスの主キーを何にするか」という判断です。契約番号やコードのような業務上の識別子(業務キー/自然キー)を主キーにするのか、それとも pyGUID のようなシステム生成の代替キー(サロゲートキー)にするのか。ここは一度決めると後から直すコストが最も高く、参照の壊れやすさ・一意性・単一インスタンス取得のすべてに波及します。
結論を先に言うと、判断の起点は 1 つです。
そのキー候補の値が将来変わりうるなら、業務キーを主キーにしてはいけない。可変ならシステム生成の代替(サロゲート)キーを主キーにし、業務属性は一意制約で別に担保する。真に不変な識別子があるときだけ業務キーを主キーにしてよい。
「人が読めるから」「業務的に意味があるから」という理由で可変な業務属性を主キーにするのは、キー設計で最も多い失敗です。可読性と主キー適性はまったく別の軸です。本記事では、この判断を具体的な分岐に落とし込み、一意性をどう担保するか、キー付きデータページとどう関係するかまでを整理します。
Pega の永続化インスタンスとキーの基礎
キーの話をする前に、Pega の永続化インスタンスがどうやって識別されているかを押さえておきます。ここが曖昧なままだと、業務キーと代替キーの議論が空中戦になります。
Pega で永続化された(データベースに保存された)インスタンスは、例外なく次の 2 つを持ちます。
pxObjClass— そのインスタンスがどのクラスに属するかを表す。どの表・どのルールに従うかの起点。pzInsKey— インスタンスを一意に識別するハンドル。1 レコードを一意に指し示す内部的なキー。
pzInsKey は、多くの場合「クラス名 + そのクラスで定義したキー値」を組み立てて生成されます。つまり クラスルールでどのプロパティをキーとして定義したかが、そのまま pzInsKey の実体を決めるということです。ここで「値が変わりうるプロパティ」をキーに選んでいると、その値が変わった瞬間に pzInsKey の前提が崩れ、そのインスタンスを指していた参照が宙に浮きます。
pzInsKeyの内部的な組み立て方はバージョンやクラス構成により差があります。細部は利用中の版の公式ドキュメントで確認してください。本記事で重要なのは「キー定義がインスタンスの同一性そのものを決める」という点です。
データクラスのキーは、クラスルール上で 業務キー(自然キー)を割り当てるか、システムが生成するキー(代替キー)を割り当てるかを設計者が選びます。この選択が、以降のすべての設計判断の土台になります。
業務(自然)キーと代替(サロゲート)キー
業務キー(自然キー)の性質
業務キーは、契約番号・商品コード・注文番号のように 業務の世界にもともと存在する識別子 をそのまま主キーにするアプローチです。最大の長所は 人が読めること、そして意味のある値なのでログやレポート、システム間の突き合わせで扱いやすいことです。
弱点は 値が変わりうること に尽きます。「そのコード体系は絶対に変わらない」と設計時に信じていても、業務ルールの変更・組織再編・採番体系の刷新で値が変わる例は珍しくありません。主キーの値が変わると、そのキーで参照していたすべての箇所が壊れます。参照は値のコピーで成り立っているため、参照先の値だけを直しても参照元は古い値のまま取り残されるからです。
代替キー(サロゲートキー)の性質
代替キーは、pyGUID のように システムが生成する、業務的意味を持たない値 を主キーにするアプローチです。生成後は決して変えない前提で運用するため、値が安定していて参照が壊れないのが最大の長所です。業務属性がいくら変わっても、レコードの同一性は代替キーが保証し続けます。
弱点は 人間可読性がないこと。GUID を見ても人はどのレコードか判別できないため、業務上の識別(検索・突き合わせ)には別途、業務属性(コードや番号)を 一意属性として 持たせる必要があります。つまり代替キーは「同一性の担保」を、業務属性は「人が探すための鍵」を分担します。
比較表
| 観点 | 業務(自然)キー | 代替(サロゲート)キー |
|---|---|---|
| 値の由来 | 業務上の識別子(契約番号・コード等) | システム生成(pyGUID 等) |
| 人間可読性 | 高い | 低い(無意味な文字列) |
| 値の安定性 | 業務ルール次第で変わりうる | 不変(生成後は変えない前提) |
| 参照の壊れやすさ | 値が変わると参照が壊れる | 壊れない(値が変わらない) |
| 業務検索のしやすさ | そのまま鍵になる | 別途、一意属性が必要 |
| 向いている場面 | 真に不変な識別子がある | 可変属性しか識別子がない/将来変更の可能性 |
| 既定の判断 | 例外的に選ぶ | 迷ったらこちら |
判断の型はシンプルです。キー候補の値が「絶対に、業務ルールが変わっても変わらない」と言い切れないなら代替キーを主キーにする。 言い切れる真に不変な識別子があるときだけ、業務キーを主キーにする——これが実務での既定です。
一意性をどう担保するか
主キーの選択と並んで重要なのが「そのキーの一意性を、どこでどう保証するか」です。ここを 1 つの手段に頼ると、必ず穴が空きます。Pega では主に次の 3 つが別々の層で働きます。
1. DB の一意制約/一意インデックス(ストレージ層)
データベース側で一意インデックスまたは一意制約を張り、同じキー値の 2 レコード目の保存を物理的に拒否します。最終防衛線であり、これが無いと他の手段をすり抜けた重複が最終的にテーブルに入り込みます。反面、アプリ側で事前に弾いていないと、保存の瞬間に DB エラーとして跳ね返り、利用者体験が悪くなります。
2. アプリケーション層のバリデーション(一意性チェック)
保存前にアプリ層で「その値は既に存在しないか」を検査し、利用者に分かりやすいエラーとして重複を差し戻す仕組みです。Pega では Validate ルールや制約(Constraints)ルール、データ型のフィールド検証などで実装します(該当機能の名称・設定箇所はバージョンにより異なるため、実装時は公式ドキュメントで確認してください)。UX 上は必須ですが、これだけでは競合状態(ほぼ同時の 2 つの保存が、互いに相手の存在を検知できないタイミング)で重複が DB に入りうるため、DB 側の一意制約と組み合わせて初めて堅牢になります。
3. キー付きデータページのキー定義(取得層)
後述するキー付きデータページで単一インスタンスを取得する前提が、この「キーが本当に一意であること」です。ここでのキー定義は 取得を正しく成立させるための宣言 であり、これ自体は重複の発生を防ぎません。既に重複が存在すると、取得側で取り違えが起きるだけです。
| 担保手段 | 効く層 | 単独だと空く穴 |
|---|---|---|
| DB一意制約/一意インデックス | ストレージ層 | アプリ側で事前検知できず保存時エラーで UX 悪化 |
| アプリ層のバリデーション(一意性チェック) | アプリケーション層 | 競合状態で DB に重複が入りうる |
| データページのキー定義 | 取得層 | 既存の重複を防げず、取得で取り違える |
3 つは役割が違うので、原則すべてを併用します。 「DB 制約があるからバリデーションは不要」「バリデーションしているから DB 制約は不要」という片手落ちが、後から最も痛い重複バグを生みます。
キー付きデータページとキー設計の関係
キー付きデータページ(Keyed Data Page)は、キーを 1 つ渡すと単一インスタンスを 1 件返すためのデータ取得の仕組みです。ケースから特定のマスタレコードを引くとき、リスト全体をロードして絞り込むのではなく、キーで直接 1 件を取得できるため効率的です。
ただしこの仕組みは、渡されたキーで一意に 1 件が定まることを前提にしています。キー設計を誤ってキーが実は一意でなかった場合、次のような破綻が起きます。
- 単一取得が破綻する — 同じキー値に複数レコードが該当すると、単一インスタンス取得はどれを返すか保証できず、意図しない 1 件が返る。
- リスト取得での取り違え — キーで結合したつもりの一覧が、重複により誤った行と対応づいてしまう。
つまりキー付きデータページは、キー設計の正しさを 実行時に容赦なく突きつけてくる コンポーネントです。「主キーに可変属性を選ぶ」「一意性を担保しきれていない」といった設計上の甘さが、ここで単一取得の破綻・リストの取り違えという形で表面化します。逆に言えば、代替キーで同一性を安定させ、一意性を 3 層で担保しておけば、キー付きデータページは素直に機能します。
よくある失敗
キー設計の失敗は、経験上いくつかの決まったパターンに収束します。
失敗1:可変な業務属性を主キーにする
最も多く、最も痛いのがこれです。メールアドレス・電話番号・氏名 といった「一見ユニークだが変わりうる属性」を主キーにしてしまうパターン。設計時点では一意に見えても、これらは利用者の都合でいつでも変わります。値が変わった瞬間に pzInsKey の前提が崩れ、そのレコードを参照していた箇所がすべて宙に浮きます(参照崩壊)。
正しくは、同一性は不変の代替(サロゲート)キーに持たせ、メールや電話は「一意属性」として別に持つ。こうすれば、メールが変わってもレコードの同一性は代替キーが守り、参照は壊れません。一意属性側には一意制約を張って重複登録を防ぎます。
失敗2:一意性の担保が片手落ち
「アプリでバリデーションしているから DB 制約は要らない」あるいはその逆で、1 つの層だけで一意性を守ろうとする パターン。前述のとおり、アプリ層のバリデーションだけでは競合状態で漏れ、DB 制約だけでは UX が荒れます。3 層は役割が違うので、原則すべて併用します。
失敗3:キーに意味を詰め込みすぎる
可読性やソート都合のために、複数の業務属性を連結した「意味の詰まったキー」を主キーにするパターン。連結した属性のどれか 1 つでも変わりうるなら、それは可変キーと同じ問題を抱えます。キーに業務的な意味を負わせるほど、その意味が変わったときの破壊力が増します。 意味は属性として持ち、同一性は無意味で不変な代替キーに任せるのが安全です。
失敗4:キーが一意でないままキー付きデータページを使う
一意性の担保が甘いまま単一取得を組んでしまい、本番でたまたま重複が入った瞬間に取り違えが発生するパターン。単一取得を設計する時点で、そのキーが 3 層で一意に守られているかを必ず確認します。
判断の型(まとめ)
- 主キーは「値が変わりうるか」で決める。 変わりうるなら代替(サロゲート)キー、真に不変なら業務(自然)キー。可読性は判断軸ではない。
- 代替キーを選んだら、業務検索用に一意属性を別に持たせる。 同一性は代替キー、探すための鍵は業務属性、と役割を分ける。
- 一意性は 3 層で担保する。 DB 一意制約(ストレージ)+ アプリ層のバリデーション(アプリ)+ データページのキー定義(取得)。どれか 1 つに頼らない。
- キー付きデータページは、キー設計の正しさを実行時に突きつける。 一意でないキーは単一取得の破綻・取り違えとして必ず表面化する。
まとめ
キー設計はデータモデルの土台であり、後から直すコストがモデルの中で最も高い箇所です。だからこそ、設計の初手で「値が変わりうるか」という 1 問を言語化し、可変なら迷わず代替(サロゲート)キーを主キーにする——この判断を機械的に下せる型として持っておく価値があります。
Pega は永続化インスタンスを pzInsKey と pxObjClass で識別し、そのキー定義がインスタンスの同一性そのものを決めます。可変な業務属性を主キーにすれば同一性が揺らぎ、参照が崩壊します。同一性は不変の代替キーに、業務検索は一意属性に、一意性はストレージ・アプリ・取得の 3 層に——それぞれ役割を分けて設計しておけば、キー付きデータページも素直に機能し、後工程での大きな手戻りを防げます。
Pega のデータモデル設計・キー設計でお困りの際は、Pega Platform 開発支援 や 無料相談 をご利用ください。Pega 認定資格の最高位 LSA(Lead System Architect)を保有するコンサルタントが、設計判断からご支援します。
関連リンク
関連記事
Pega 宣言的処理のコスト設計|前方連鎖と後方連鎖の使い分け
Declare Expression は便利だが、前方連鎖のカスケードは1つのプロパティ変更が広範な再計算を引き起こす。宣言的処理は「書けば動く」半面、実行コストが見えにくい。本記事は前方連鎖と後方連鎖、宣言的と手続き的の境界線を、性能と保守性の観点で整理する。
記事を読むPega Insights と Report Definition の使い分け|セルフサービス分析と運用レポートの線引き
「レポートは Report Definition で作るべきか、Insights でユーザーに任せるべきか」——ダッシュボード設計で必ず出る分岐です。統制と再利用が要る定型レポートはルール化し、アドホックな探索はセルフサービスに開く、が基本方針。本記事では両者のガバナンス差とデータソースの前提から、線引きの判断軸を示します。
記事を読むPega 監査証跡設計:フィールド監査・履歴・セキュリティ監査の使い分け
「何を、どこまで監査するか」は Pega のセキュリティ設計で最も判断が割れるテーマです。フィールド監査・ケース履歴・セキュリティイベントの使い分けと、監査のかけ過ぎが招く性能・容量問題の回避策を、LSA の視点で解説します。
記事を読む