その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

補足: 履歴テーブル、今回はこう作りました 〜 Delegated Types編 〜

Ruby on Railsのテーブル設計とトランザクション処理 LT Night」で話した内容のフォローアップです。主に懇親会で id:kamipo さんから現地でもらった質問を受けての補足となります。

speakerdeck.com

図中のオレンジ枠と緑枠のトランザクションを分けているのはなぜ? ログレコードが保存できてイベントレコードが保存できないことなんてなくない?

説明がスッポリ抜けていたのですが、ASPからwebhookを受けて諸々の処理をする部分は非同期処理になっているのでそもそもライフサイクルごと分かれていたのでした。つまり、webhookを受けたタイミングでログレコードを記録してからキューイングし、それを非同期的にイベント処理をするので必然的にトランザクションが分かれる。

それはそうとして、イベントを扱う処理中に不慮のクラッシュが発生した時にロギングが巻き込まれると後の調査タスクに影響するので、防御的に作っているというのはそうです。

なぜ非同期処理にしているの?

必ずしもオンラインでやる必要が無いため。キューイングして非同期でやったほうが何かと取り回しが良い (後回しにできるものはしておくと最適化の余地が出てくる)。

enrollment_intentsとconversionsは同じテーブルで扱って良かったのではないか?

enrollment_intentsはユーザーの参加意図を表現していて、conversionsはその参加意図からの実際の参加を表現している。データモデル的には同一に扱えるかもしれないが、行動実態に照らし合わせると別にしたほうが分かりやすい。データを発生させる主体に注目するとenrollment_intentsはユーザーの能動的行動、conversionsはASPからのwebhook受信、とそれぞれ異なるのでライフサイクル的に別物であるという捉え方ができる。
またサービスの特性上、enrollment_intentsのデータ量とconversionsのデータ量は大きく異なる (離脱があるため前者の方が明確に多い) という背景もあり、テーブルを分けているという実情でした。

Delegated TypesじゃなくてSTIで十分だったんじゃないか?

それは本当にそうかもしれない……とはいえ今後の拡張 (提携する事業者が増えるなど) を考えると各ステートのテーブルのcolumnや振舞いが増える可能性が十分にあるので拡張の余地を残すべくDelegated Typesを採用したという背景があります。

スライド中の補足にも書きましたがDelegated Typesだとクエリ数が増え、気を抜くとN+1製造機になるというconsもあるので、そのパフォーマンス面を考慮するとSTIを選択するというのもありかもしれません。

各ステートのテーブルにuser_idとか入れといた方が良さそうじゃない?

それは本当にそう!!!!!!!!!! 絶対に後で必要になるので今入れます。

off-topic: Ruby 4.0.0 preview2とZJITって速い?

まだ評価できるほどのトラフィックを流していませんが、俺は信じています。あとZJITはまだ性能評価の前段階にあるという認識です。俺は信じています。




その他にも、

  • RDBMSのカッチリしたテーブル構造とJSON型のcolumnを組み合わせたハイブリッドな構成は今となってはアリなのではないか
    • MySQLにもCHECK制約がやって来たのでJSONのvalidationをCHECK制約により行えるし、pgであればpartial indexを使えばJSONであっても現実的にindexを張れる、などなどJSON型を取り巻く状況は以前とは変わっているから
    • それはそうとして適切な用途にはDynamoDBを使いたくはある (経験があるので)、新機軸としてDSQLも気になる
      • 用途に応じて保存するストレージを分けられるようになったというのは昨今のアーキテクチャの進歩ではないか
  • user tableをどのように作るか
    • 1つの巨大テーブルとして扱うか、適切にテーブル分割をするか、するとしてどのような基準で分割するか
    • 拡張 (例えばALTER時) が辛くなるのであれば分割のサインなのではないか、など
  • スライド中にワイプのようにER図を表示すると便利そうだと思って今回のスライドに入れてみた (36ページ目) けれど時間が無くてみなさんにお見せできなかった

などという話題がありました。楽しかったですね。

[追記]
補足の補足をいただきました: