persistent_id について#
canonical_id についてで触れた通り、canonical_id は不変であることが保証されておらず、場合によっては今まで同一人物であったユーザーに対して異なる canonical_id が割り振られてしまうことがある。
この問題に対処するために canonical_id と同様の設定方法で、ほぼ永続的に不変な値を保持する仕組みが追加された。これを persistent_id と呼ぶ。この章では persistent_id の特徴と設定方法について紹介していく。
Note
persistent_id を canonical_id の代わりに使用する場合、利用者は merge_by_keys:
の設定に悩むことなく、不変のIDを得ることができる。
Warning
persistent_id は do_not_merge_key には対応していないので注意が必要である。
persistent_id が不変な値を保持する仕組み#
以下のレコードがあった際の、canonical_id と persistent_id それぞれの値を生成する仕組みを見ていこう。
Day |
td_client_id |
td_global_id |
---|---|---|
2024-03-01 |
aaa_002 |
3rd_001 |
2024-03-02 |
aaa_001 |
3rd_001 |
設定方法は以下の通りで、どちらも同じ記述方法となる。
canonical_ids:
- name: cid
merge_by_keys: [td_client_id, td_global_id]
persistent_ids:
- name: pid
merge_by_keys: [td_client_id, td_global_id]
canonical_id の生成方法#
この設定の元では、merge_by_keys:
の並び順において優先度の高い td_client_id の値の中で(文字列の意味で)最小の値aaa_001
が leader に選ばれ、この値をベースに canonical_id が生成される。
persistent_id の生成方法#
一方、persistent_id では、td_client_id の中で、時間の意味で最小の値が leader に選ばれるため、今回の場合は aaa_002
が leader となり、この値をベースに persistent_id が生成される。(leader をベースにした生成式自身は変わらない。)
例1: leader として選ばれる key 値の日ごとの変遷#
persistent_id がどのように生成されるかを理解するために、日ごとのデータの追加に伴う leader の変遷を見ていこう。
1日目#
Day |
td_client_id |
td_global_id |
---|---|---|
2024-03-01 |
aaa_002 |
3rd_001 |
上記の1日目の時点では、
Day |
canonical_id における leader |
persistent_id における leader |
---|---|---|
2024-03-01 |
aaa_002 |
aaa_002 |
となる。
2日目#
Day |
td_client_id |
td_ssc_id |
---|---|---|
2024-03-01 |
aaa_002 |
3rd_001 |
2024-03-02 |
aaa_001 |
3rd_001 |
翌日のデータが上記のように追加されると、それぞれの id における leader は以下のようになる。
Day |
canonical_id における leader |
persistent_id における leader |
---|---|---|
2024-03-01 |
aaa_002 |
aaa_002 |
2024-03-02 |
aaa_001 |
aaa_002 |
canonical_id の方では leader が前日と異なっているために、新たな canonical_id の値が生成されることを意味する。一方で persistent_id では leader が変わっていないため、前日と同じ persistent_id の値が生成される。
このように、persistent_id は(merge_by_keys:
の優先度の高い key から順に)常に時間的な意味で最小の値を leader にするために、その後どんな値の key が登場したとしても、leader の値が変わることはない、これは persistent_id が不変な値を保持する仕組みである。
例2: 2人の人物が紐づいた際の persistent_id の挙動#
より過去の key の値が leader に選ばれるということは、2人の人物がある時点で紐づいた際に、より過去の key の値を持つ人物の方の key にマージされることを意味する。以下に例を見てみよう。
Day |
site_aaa |
site_aaa |
site_bbb |
site_bbb |
---|---|---|---|---|
td_client_id |
td_global_id |
td_client_id |
td_global_id |
|
2024-03-01 |
bbb_001 |
3rd_001 |
||
2024-03-02 |
aaa_001 |
3rd_002 |
||
2024-03-03 |
aaa_001 |
3rd_001 |
この時の、leader として選ばれる値の2日目以降の変遷を見てみよう。前回と同様に
canonical_ids:
- name: cid
merge_by_keys: [td_client_id, td_global_id]
persistent_ids:
- name: pid
merge_by_keys: [td_client_id, td_global_id]
の設定であったとする。
2日目#
Person 1#
Day |
canonical_id における leader |
persistent_id における leader |
---|---|---|
2024-03-02 |
bbb_001 |
bbb_001 |
Person 2#
Day |
canonical_id における leader |
persistent_id における leader |
---|---|---|
2024-03-02 |
aaa_001 |
aaa_001 |
3日目#
Person 1 = Person 2(マージ)#
Day |
canonical_id における leader |
persistent_id における leader |
---|---|---|
2024-03-03 |
aaa_001 |
bbb_001 |
このケースの場合、canonical_id では Person 1 側の leader にマージされるのに対し、persistent_id では Person 2 側の leader にマージされることになる
例3: より優先度の高い key が登場しても persistent_id は不変#
以下の設定のおいて、
persistent_ids:
- name: pid
merge_by_keys: [td_client_id, td_global_id]
ある User1 の以下のようなデータの例を考えよう。このユーザーは、merge_by_keys:
の意味で優先度の高い td_client_id が後日登場するケースである。
Day |
site_aaa |
site_aaa |
site_bbb |
site_bbb |
---|---|---|---|---|
td_client_id |
td_global_id |
td_client_id |
td_global_id |
|
2024-03-01 |
3rd_001 |
|||
2024-03-02 |
3rd_001 |
|||
2024-03-03 |
aaa_001 |
3rd_001 |
この場合、canonical_id と persistent_id 双方において 2024-03-02 までは 3rd_001
が選ばれることになる。しかし、2024-03-03 になると、td_client_id の値が紐づくことになるため、leader の値が変わる可能性がある。この日においてそれぞれの id における leader を考えてみよう。
canonical_id の場合#
canonical_id では、優先度の高い key が現れた場合には、文字列の大小に関係なく優先度の高い key の値が leader となっていた。

Fig. 32 canonical_id では、優先度の高い key が現れた場合には、文字列の大小に関係なく優先度の高い key の値が leader となっていた。ゆえに、canonical_id もこの時点で変わることになっていた。#
persistent_id の場合#
persistent_id の場合は、優先度の高い key が現れた場合でも leader の値、つまり persistent_id の値は変わらないのである。
実は persistent_id では、標準では time
が優先度の高いものとして考えられる。つまり persistent_id における merge_by_keys:
の設定は(time を明示しない場合)、
persistent_ids:
- name: pid
merge_by_keys: [time, td_client_id, td_global_id]
となっている。この設定の元では、最小時間のいずれかの key の値が leader となるため、以後優先度の高い key が登場したとしても leader の値が変わることはないのである。

Fig. 33 persistent_id では、時間最小のいずれかの key が leader に選ばれると、優先度の高い key がその後登場しようと、「時間最小である」ことが最優先されるため、leader の値が変わることはない。つまり persistent_id の値は変わらないことになる。#
persistent_id の値が途中で変わってしまうケース#
persistent_id が途中で変わってしまうケースは、
Case1. 過去のレコードが追加された時、過去のレコードが削除された時#
この場合、最も過去のレコードが途中で変わってしまうことになるため、その時の key の値が変わるため、leader も変わることになる。故に persistent_id の値が変わってしまう。
Case2. merge_by_keys: の設定で、time より優先度の高い key を指定した場合#
persistent_id では、time という key を merge_by_keys:
の設定の中に入れることができる。これについては次章で紹介しよう。
persistent_id における merge_by_keys: の設定#
persistent_id における merge_by_keys:
の設定は、time というキーが潜在することになる。time を明示しない場合、例えば
persistent_ids:
- name: pid
merge_by_keys: [td_client_id, td_global_id]
の設定は、以下と同義になる。
persistent_ids:
- name: pid
merge_by_keys: [time, td_client_id, td_global_id]
これに対し、
persistent_ids:
- name: pid
merge_by_keys: [td_client_id, time, td_global_id]
のような設定をすることができる。この場合では、time より td_client_id が優先されるため、先ほどの例
Day |
site_aaa |
site_aaa |
site_bbb |
site_bbb |
---|---|---|---|---|
td_client_id |
td_global_id |
td_client_id |
td_global_id |
|
2024-03-01 |
3rd_001 |
|||
2024-03-02 |
3rd_001 |
|||
2024-03-03 |
aaa_001 |
3rd_001 |
においては 2024-03-03 時点において、leader が aaa_001 となるため、persistent_id の値が変わってしまうことになる。このように time よりも優先させたい key がある場合には、明示的に time より優先させる記述をすることができる。ただし、その場合には persistent_id の値が途中で変わってしまう可能性があることに注意しよう。