RDBのデータモデリング・テーブル設計の際に参考にしている考え方と資料

# はじめに
タイトルのとおり、RDBのデータモデリング・テーブル設計を行う際に参考にしている考え方と関連資料をまとめました。

P.S.
なんと本記事内でいくつか参考として挙げさせてもらっている増田さん・かとじゅんさん・奥野さん・そーだいさんからコメントいただくことができました。
本当にありがとうございます。

https://twitter.com/masuda220/status/1506431537755033601

https://twitter.com/j5ik2o/status/1506621151816355844

https://twitter.com/j5ik2o/status/1506621796417945600

https://twitter.com/nippondanji/status/1506587961303117824

https://twitter.com/soudai1025/status/1506580016909647880

# 前提

## RDBを採用するのは事実を無駄なく正しく記録するため

- 正規化、トランザクション、制約とデータ整合性
    - 基本的には始めに理想として集合論・リレーショナルモデルに基づいて正規化を考え(論理設計)、パフォーマンスなどの現実問題に対して折り合いをつけていく(物理設計)
    - 制約を最大限利用する

cf: 

https://speakerdeck.com/soudai/rdb-the-right-way?slide=91

↑P91〜

https://overcast.fm/+h9VS95rR8

https://www.slideshare.net/nippondanji/ss-55613684

↑P.29,41

https://speakerdeck.com/soudai/webenzinianizhi-tutehosiirdbantipatan?slide=56

↑P56〜

https://www.shoeisha.co.jp/book/detail/9784798124704

↑5章

https://gihyo.jp/book/2015/978-4-7741-7197-5

↑P347～

## 情報とデータ

- データ：単なる事実の値→これを永続化して蓄えるものがRDB
- 情報：データから生み出される意味や目的のあるもの→RDBから情報を生成するのに適しているものがSQL
- つまりRDBの設計(データをどう正しく保存するか)とSQL(情報をどのように取得するか)は関連はあるが別の関心事である

cf:

https://speakerdeck.com/rtechkouhou/ye-wu-sisutemugou-zhu-niokerudetamoderingu?slide=9

↑P9

https://speakerdeck.com/soudai/rdb-the-right-way?slide=26

↑P26〜

https://eh-career.com/engineerhub/entry/2018/12/11/110000#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%A8%E6%83%85%E5%A0%B1%E3%81%AE%E9%81%95%E3%81%84
 
https://www.oreilly.co.jp/books/9784873115894/

↑まえがき

## 更新(UPDATE)は複雑さを生む

- そもそも集合論的に更新はない
- 更新には複雑なルールを伴うため、極力更新を避けられないか
- 更新と削除がなければ事実・データが失われることがない
- 思考の制約として更新と削除をしないと考えると見落としている概念やモデルを見つける事ができる
    - という背景・考え方がある

cf:

https://overcast.fm/+h9VS95rR8

https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

https://www.slideshare.net/kawasima/ss-250716400

https://www.slideshare.net/kawasima/ss-40471672

https://www.slideshare.net/kawasima/ss-44958468 

https://gihyo.jp/book/2017/978-4-7741-9087-7

↑6章

https://gihyo.jp/book/2015/978-4-7741-7197-5

↑1章,7章

羽生章洋さん

佐藤正美さん


# 観点

## 典型的アンチパターンを踏んでいないか / テーブル・カラムの責務は適切か

- [SQLアンチパターン](https://www.oreilly.co.jp/books/9784873115894/)や[そーだい本](https://www.amazon.co.jp/dp/B07P8PMHLL)、[データベースリファクタリング](www.amazon.co.jp/dp/4894715007)に指摘されているような問題を踏んでいないか
- テーブルがファットになっていたり、1つのカラムが複数の意味を持ったり、複数のカラムを組み合わせることで初めて意味が成立するようなカラム持ったりしていないか
    - 個人的にこれらは正規化と短絡的な更新を避けるようにしていればこうした問題を踏みにくいという印象を持っている
    - アンチパターンとして紹介されているもの内、一部は時代的に古かったり賛否両論あるものも含まれているようなので鵜呑みには注意

cf: 

https://www.slideshare.net/t_wada/sql-antipatterns-digest

 ↑監修者t_wadaさんのスライド

https://qiita.com/fktnkit

↑SQLアンチパターンの内容を紹介してくれている記事をたくさん書かれてらっしゃる方

https://speakerdeck.com/soudai

↑そーだいさんのスライド。データベースリファクタリングやアンチパターン系のスライドで紹介されている。一見同じようなタイトルでも紹介されている中身が違ったりする。

https://speakerdeck.com/soudai/rdb-antipattern-refactoring?slide=38

↑P38

https://speakerdeck.com/soudai/learn-from-failure-1?slide=82

↑P82〜

https://www.shoeisha.co.jp/book/detail/9784798124704

↑7章

## マスタとトランザクション
  
- エンティティの分類としてマスタとトランザクションは人によって定義が曖昧になるので、イベントとリソースで分類する方が良いのではという考え方がある

cf: 

https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

 ↑step2

https://speakerdeck.com/soudai/rdb-the-right-way?slide=51

↑P51〜

https://www.shoeisha.co.jp/book/detail/9784798110660

## 更新

- すべてのテーブルに更新ユーザー・日時は必要か
- テーブルを更新したい・ステータスが存在する・状態を持たせている→履歴や遷移の過程は残さなくて良いのか
- 更新日時が欲しい→イベントが隠れている

cf:

https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

https://su-kun1899.hatenablog.com/entry/2015/10/14/230000

https://speakerdeck.com/soudai/learn-from-failure-1?slide=15

↑P15〜

https://speakerdeck.com/soudai/rdbantipatan?slide=60

↑P60〜

https://soudai.hatenablog.com/entry/2018/05/01/204442
 
https://itohiro73.hatenablog.com/entry/2017/05/22/083201

https://www.slideshare.net/SoudaiSone/postgre-sql-54919575

↑P108〜

https://speakerdeck.com/soudai/learn-from-failure-1?slide=40

↑P40〜


https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

↑step3,4

## 削除

- 安直な削除フラグはアンチパターン

cf: 

https://www.slideshare.net/t_wada/ronsakucasual

https://qiita.com/Jxck_/items/156d0a231c6968f2a474

https://fukabori.fm/episode/27

https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

↑step4

https://www.slideshare.net/SoudaiSone/postgre-sql-54919575

↑P20〜

https://www.slideshare.net/yoku0825/mysql-52276506
 

## 交差テーブル
    
- 単に2つのテーブル名を重ねているだけで概念が隠れてしまっていないか

cf: 

https://scrapbox.io/kawasima/%E3%82%A4%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AB

↑step5

https://qiita.com/tkawa/items/dc3e313021f32fd91ca6
 

## JOINと正規化

- flag or status & where VS Join
    - 一般的にはflag or status & whereの観点の方が多い印象。
    - テーブル分割とJoinによる設計を考えると今までとは違う景色が見えるかも。
- Joinは遅いとパフォーマンスの悪化を恐れて最初から正規化を避けていないか

cf: 

https://twitter.com/masuda220/status/1452267050395521026?s=12


https://twitter.com/a_suenami/status/1450287178513145859?s=12


https://twitter.com/a_suenami/status/1450290209128472583?s=12

https://speakerdeck.com/soudai/learn-from-failure-1?slide=105

↑P105〜

https://speakerdeck.com/soudai/rdb-the-right-way?slide=98

↑P98〜

https://www.shoeisha.co.jp/book/detail/9784798124704

↑5章

https://gihyo.jp/book/2015/978-4-7741-7197-5

↑P319～

## トリガー、ストアドプロシージャー、キャッシュ

- 安易にこれらを選択していないか([データベースリファクタリング](www.amazon.co.jp/dp/4894715007)的には終わったら消す前提でリファクタリングの過程でトリガーを用いるのはあり)

cf:

https://speakerdeck.com/soudai/rdb-anti-pattern-that-java-engineer-wants-to-know?slide=53

↑P53〜

https://speakerdeck.com/soudai/learn-from-failure-2?slide=66

↑P66〜

https://www.shoeisha.co.jp/book/detail/9784798124704

↑P330～

## ID生成

cf:

https://zenn.dev/j5ik2o/articles/a085ab3e3d0f197f6559

https://qiita.com/kawasima/items/6b0f47a60c9cb5ffb5c4

## インデックスとチューニング(主にMySQL)

cf:

https://speakerdeck.com/mamy1326/what-phpers-need-to-know-about-mysql-query-tuning

https://speakerdeck.com/yoku0825/mysqltoindetukusutophper

https://www.slideshare.net/yoku0825/whereorder-by

http://nippondanji.blogspot.com/2009/03/mysqlexplain.html
 


## そもそもRDBに保存すべきか

- パフォーマンス、データモデル構造の観点から適切な保存技術を検討する。

cf:

https://www.slideshare.net/nippondanji/ss-55613684

↑P23〜

https://www.slideshare.net/nippondanji/relational-modelokunonewlong

↑P89〜

https://www.slideshare.net/nippondanji/db-engineerstudyanim

↑101〜

https://qiita.com/fktnkit/items/57033c10b41b5747dbea
 
https://www.shoeisha.co.jp/book/detail/9784798124704

↑9章

## その他観点

https://speakerdeck.com/mamy1326/what-phpers-need-to-know-about-mysql-query-tuning?slide=223

↑P223〜

https://speakerdeck.com/soudai/release-safely-2?slide=43
 
↑P43〜

# おわりに

こうしてまとめてみると川島さん、そーだいさん、増田さん、SQLアンチパターンあたりに強く影響を受けているなと思いました。

こうしてたくさんの資料を残してくださり、肩に乗せてくださっている巨人の皆様に改めて感謝申し上げます。

本当にありがとうございます。