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 となっていた。

_images/13-1-1.png

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 の値が変わることはないのである。

_images/13-2-1.png

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 の値が途中で変わってしまう可能性があることに注意しよう。