達人に学ぶDB設計入門がよかったので全力で勧めてみる

# はじめに
新卒の時に有名な本だったので一度読んだことはあったのですが

読んだ後に実践練習をしなかったので定着しないまま終わっていました。


2年目になり1年越しに読んだ感想と実際に簡易的なTwitterのDB設計を

outputとして行ったので特に参考になった部分を5点ほど自分なりにまとています！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3350234/11256f30-9f35-37d5-2f01-d250568feda7.png)



対象の方は
- DB設計の概要を知りたい方
- DB設計学ぶか悩んでる方
- DB設計学んだけどうまく利点を簡潔に言えない方
- DB設計＝正規化だと思っている方


なので、具体的な正規化の方法などには突っ込みません。

ただ結構奥深いことが分かると思うので本買って学ぶ気になると思います！


## 1. なんでDB設計が重要なのか

**要件定義** 　⇒　**設計**　⇒　**開発**　⇒　**テスト**


要件定義はクライアントの要求を正確にアプリで実現するために重要な工程なのはわかりやすいですね


### ～DB設計が重要な理由～

 - **運用のしやすさに直結する**
⇒クライアントから会社Aが新しく入ってきたから会社情報をDBに追加しといてと言われたときに
    　社員情報もなければ追加できない
　
⇒クライアントから商品Aが商品Bという名前に変わったから対応してと言われたときに
　顧客がこれまで商品Aを購入したすべての履歴を商品Bに変更しないといけない


- **開発のロジックに影響を与える**
⇒カラムの意味が途中から変わっていて、システムの変更の歴史を知っている人じゃないと
　最初理解できないSQLが存在する

  ⇒SQLに必ずNullじゃなければ○○みたいなロジックを書かないといけない

  ⇒名字と名前を分けずにDBに登録してしまっていて、名前だけ表示する要件にアプリケーション側で
　100%正確に分割はできないロジックを無理やり実装している


- **パフォーマンスに影響を与える**
⇒レコードが非常に多いテーブルでの結合を頻繁に行わなければいけない

  ⇒テーブル採番時にそのテーブルにロックがかかりパフォーマンスボトルネックになる


ひどいDB設計はエンジニアを不幸にするのでしっかり勉強しましょう（笑）


## 2. DB設計の全体の流れ
DB設計＝正規化ととらえるかたも多いのではないでしょうか？

もちろん正規化はかなり重要ではありますが、DB設計の中ではほんの一部分なんです。


まずDB設計には大きく分けて
- 論理設計
- 物理設計

の2つの工程があります。

論理設計⇒物理設計　の順番で行います。それぞれ何をするのかざっくり見ていきましょう


### 論理設計
- エンティティの抽出
- エンティティの定義
- 正規化
- ER図

エンティティとは実体という意味で　会社・社員・商品・注文履歴

など物理的実態があるにかかわらず概念的にとらえて管理しやすいまとまりのことです。

論理設計の部分は割と知っていることが多いかもしれません。

細かいところには突っ込みません。

意外と設計って思ってたよりもやることあるなと感じて頂ければ大丈夫です。

### 物理設計
- テーブル定義
- インデックス定義
- ハードウェアのサイジング
- ストレージの冗長性構成決定
- ファイルの物理的配置決定

こちらはなじみがあまりないですよね。

テーブル定義でカラムの型を決めたり、制約を付けたりします。

indexはレコードが多いテーブルのパフォーマンスを上げるために、本の索引みたいに使用します。

将来どの程度のストレージ容量が必要になりそうか、またRAIDなどのデータの冗長性やバックアップ・リカバリ設計

など決めることがたくさんあります。

またindexファイル・ログファイル・データファイルなどをどこに配置するかなども決めなくてはいけないです。

現在はクラウドを利用すれば以前より気にしなくていいことが増えたと思いますが、

クラウドを使用するならここら辺はブラックボックス化するので覚えておきたいところです。

## 3. 正規化の本質

この本の第1~5正規系で行っていたことの効果を自分なりに抽出したつもりです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございますー<br>昨日はなぜか集中できなかったので勉強早めに切り上げました<br>今日はその分気合い入れて頑張ります！😄<br>正規化の本質とは<br>データの冗長性＝更新の手間 をなくし<br>1テーブル1エンティティに可逆的に分割すること<br>これだけだと思います。<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ryoma＠ITエンジニア (@ryoma5457557831) <a href="https://twitter.com/ryoma5457557831/status/1667302475072954369?ref_src=twsrc%5Etfw">June 9, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

完全に持論です笑

もう少しかみ砕くと


***1.データの冗長性を無くす***

一つの変更でいろいろなレコードを変更しないといけないのはデータが2重3重と

重複してデータを持っているからです。


***2. 1テーブル1エンティティに可逆的に分割***



1テーブルに複数エンティティあると、新しくDBに会社情報を登録するときに

必ず社員とセットで登録しないといけないみたいなことが起こります。

可逆的に分割というのは、分割した後にちゃんと結合を行えば元に戻せる分割ということです。

簡単に言えば扱いやすい単位で後で戻せるように分割しようねって感じ。

## 4. 正規化とパフォーマンス
正規化は先ほど
> 「データの冗長性を無くす＋ 1テーブル1エンティティに可逆的に分割する」

操作と書きました。

正規化は行えるのであれば必ず行うべき最高の武器なのですが、

ただ欠点もあります。それはパフォーマンスです。

正規化はテーブルを分割するので、アプリで実際にデータをとってくる際は結合することが多々あります。

結合という操作はかなり時間がかかる操作なので正規化をするとパフォーマンスは落ちていくのです。


非正規化を行うのはパフォーマンス要件が本当に厳しくて、

いろいろな策を試したが無念に終わり最終手段として使用する思っておいてください。

そこに至る前に試すべき次善策が2つほどわかりやすく取り上げられています。



## 5.indexを意識したSQL
せっかくいいDB設計をしてindexを適切に張ったのに、SQLでその効果をぶち壊してしまうことは往々にあります。

自分もこれを書くまでは全くindexを生かすSQLを意識して書けてなかったです。(indexを意識しないといけないくらいパフォーマンスにシビアなDBにまだであったこともないのですが...)


この本はindexをどのような条件の場合に張った方がいいのかだけでなく、
どのようにファイル上に保存されているか(平衡木として保存されれる)まで書いてあるので


**「なぜこのSQLを書くとindexが生かせなくなってしまうのか？」**

まで理解できると思います。

- index列に対して　演算を行っている
- index列に対して　SQL組み込み関数を使用している
- index列に対して　IS NULL・否定・ORを用いている
- index列に対して　前方一致以外のLIKEを用いている
- index列に対して　暗黙の型変換を行わせている

他にもあるとは思いますがこのようなケースをピックアップされていました。


## 最後に

この本を2回読んでみて得るものが本当に大きかったので紹介してみました。

正直この本の具体的な内容をまとめたところで、端折った大事な部分を知らずに

DB設計を理解したと満足してしまうのもどうかなと感じるので言葉のまま”紹介”させて頂きました。

少しは魅力を感じて頂けましたか？

Webエンジニアなら必読の本だと思います😊(回し者ではなく客観的な意見なのでご安心を笑)。


あと余談ですが自分はこの本を読んだ後知識を定着させるために簡易的にtwitterのDBでoutputしました。


例えば
- フォロー機能
- リツイート機能
- いいね機能
- DM機能


などなど自分でtwitterの機能にはDB設計にうってつけなので参考にしてみてください！！