Baseball Play Study mini〜野球でデータモデリング(BPStudy#187) https://bpstudy.connpass.com/event/277381/
プロ野球を”データモデリング”したら沼にハマってしまった件gothedistance a.k.a ござパイセンhttps://twitter.com/gothedistanceBPStudy#187 at 2023.03.29
View Slide
YUMOTO MichitakaHello!2● ゆもと みちたか(ござパイセンというHNで生きてます)● 1979年生まれです。松坂世代。● GoTheDistanceというブログを書いてます。たまに。● 新卒SIer→雑貨製造業で内製→独立してもうすぐ7年。● Flutter/React/T3 Stack等のフロントエンド好き● やきうを愛する東京ヤクルトスワローズのファン!
BPStudy History● BPStudy#79(野球)● BPStudy#91(野球)● BPStudy#92● BPStudy#100(野球)● BPStudy#103(野球)● BPStudy#108● BPStudy#112(野球)3● BPStudy#115(野球)● BPStudy#122● BPStudy#124(野球)● BPStudy#127(野球)● BPStudy#140(登板回避)● BPStudy#142● BPStudy#185(Flutter)● BPStudy#187(NEW)
お話させて頂くこと4➔ プロ野球をデータモデリングしたら沼だった➔ 2023年シーズンの抱負➔ 謝辞
RDBデータモデリング現実をデータベースの世界に落とし込め15
データモデリングはエンティティの抽出が9割6目に見えないソフトウエアは概念を明文化して共有するのだ➔ データモデリングのコアは「エンティティ」の抽出。➔ 自分たちが作ろうとしているソフトウエアで取り扱うデータに名前をつけ、実態として認識できるように命名付けた概念=エンティティ。名称 内容 例(ホテルの予約システム )ヒト そのシステムを利用する人達社員(役職・部門等)、取引先、得意先、アルバイト。モノ システムで取り扱う資産・サービス プラン・予約・お部屋・設備・カレンダーコト システムを通じて行われる行動・イベント予約受付・問い合わせ・オンライン決済・キャンセル・空き状況を確認する
正規化 is 何7ライフサイクルが違うものは別のテーブルに切り出せ➔ 一番良くわからなかった概念が、正規化だった。今でもちょっとあやしい。➔ 正規化における「重複を排除せよ」は「ライフサイクル」の違うエンティティは必ず分離しろでよくない?よくなく なくなく なくなく ない?➔ それを進めていけば、イミュータブル・データモデリングへと繋がるのでは?➔ 予約のデータを作るのにプランが予約の中に入ってしまったら、新しい予約を作る時に必ず新しいプランが作られてしまう。➔ 予約とプランは別々のライフサイクルを持っているので、エンティティ分けよう。➔ こう考えれば勝手に第3正規形までいくだろ多分
ペナントレースで必要なエンティティを出そう28
9この1枚からすべてが始まる。さぁモデリングをしようじゃないか!
ざっとこんだけのエンティティが必要だな10試合 開催日時、場所、経過時間、予告先発、勝利投手、敗戦投手、セーブ等チームと選手 チーム変わったりするよね。うん。それと選手は全員要るよね打順 ラインアップですね。選手は当然交代するので。ポジション 1〜9、及びDH。Enumでアプリ側で持っても良さげ。増減がないので。スコアボード イニング毎の得点、ヒット数等を掲載する必要がある。1球速報 1球ごとにカウント変わり得るので。球数も出す必要がある。交代履歴 投手及び野手の交代の履歴。試合毎の成績 打者成績(打率とHRはマスト)と投手成績開催日程 ペナントレースの開催日程に応じて成績表を出す必要があるため。
試合エンティティを考える11-- 開催日時- 開催球場- ホームチームID- ビジターチームID- ホーム予告先発- ビジター予告先発- ホーム得点数- ビジター得点数- 勝利投手- 敗戦投手- セーブ- 観客数- 試合時間試合エンティティ- ID- 名称球場- ID- チーム名- 所属リーグチーム- ID- 登録名- ポジション- 背番号プレイヤー➔ 正規化を崩すべきか悩む所◆ 球場名はネーミングライツで同じ場所でも呼称が変わる為。チーム名も同様。◆ シーズン年度と名称だけを持つエンティティ作って、シーズン年度でWHERE?➔ チーム・プレイヤー・球場はマスタから参照すべきだ。固定値を埋めることは考えにくい。➔ セーブは NULL許容カラムしかない?➔ 審判も球審・塁審 x 3 が必要だ。1 : 1 の別エンティティ? カラム追加?➔ リクエストの残り回数も管理が必要だとすると、どこに保管すべきデータ?
スコアボードエンティティを考える12- 試合ID- イニング数- チームID- 得点- 四球- 安打数- エラーイニング➔ スコアボードはテーブルで表現できない気がしている。イニングの集合体がスコアボードなので、SQLでデータ取得→アプリ側でスコアボードのUIに沿ったデータを作るしかないのでは?➔ 仮にスコアボードテーブルを作る場合、どういう設計にしていくのか???➔ イニング毎に記録する数字が多いので、縦に持つしかない。➔ ノーゲーム・雨天コールド・延長戦等、消化するイニング数が試合によって異なる。その点を踏まえても、イニングを積むしかなさそう。➔ 裏の攻撃がなく試合が終わることが結構ある。9回表で試合終了するケースには「X」がスコアボードにつくけど、まさかDB側にXを保存するわけにもいかんだろ・・・
カウントとランナー表示を考える13➔ カウントは1球毎に異なる場合もあれば、4球投げても同じこともある。➔ ストライクとボールカウントは0になり、アウトカウントも3つ目で0になる。➔ 最大要素数が決まっているので単純に配列で持てば良さそう。➔ 状況によってリセットされる性質があるので、SQLでカウント表示を表現するのは出来ないように思うけど、まさか方法があるんだろうか・・・?➔ ランナーもリセットされる。塁とランナー存在フラグを持つオブジェクトを作り、1塁2塁3塁の3つのフィールドを持たせるだけで良さそうだが、改良の余地はあるか???
成績表示を考える14➔ 横持ちが簡単そうでいいけど、UPDATEの嵐になるデータ操作は正しいのか?- 試合ID- プレイヤーID- 球数- 奪三振- 与四球- 与死球- 失点- 自責点- アウトカウント投球履歴➔ 横に持った場合、1球投げる毎に投球数や被安打を更新することになる。すげーミュータブルなデータになってしまう。➔ 1球投げる毎にレコードを追加して縦に持った場合、歯抜けなデータの持ち方になるけど、GroupByで頑張ればできそう。➔ 横持ちした場合、被安打や打者等はただインクリメントするだけだけど、縦持ちした場合、三振とかヒットのような結果はどこで保存すべきなんだ・・・?!
野手成績表示を考える15➔ このUI作るの大変じゃないか・・・?➔ 打数と打席数が一致しない。四死球は打数にカウントされない。◆ 第1打席は三振、第2打席は四球等の履歴は、別テーブルで保持する必要があります。➔ 代走・守備固めでの出場があるので、代走の場合は盗塁だけ、守備固めの場合は失策のみが計上されるケースがありえます。打席が与えられないケースもあるので、打席の履歴は別。➔ 選手が起用される毎に 1レコード増やし、初期値は打率以外は全部 0。打率はこのテーブルの最後の1件を取り、プレイが完結したら UPDATEしていく以外、ちょっと思いつかなかった。
野球データモデリングは沼100テーブル前後の業務システムよりも設計が難しい(当社比)ペナントレースを表現できるER図とSQL書ければ上級者だろ・・・スポナビの野球担当エンジニアの方、3時間34分この話をしませんか・・?!16
The die is cast.Let’s go for October!Thanks!17あかん、優勝してしまう◉ @gothedistance◉ [email protected]