本当にあったやらかしDB設計①【R無しRDB】

どうも、IT業界は4年目だけど開発はあんまりやったことがなかった人です

独学でDBとアプリ周りを勉強して最近開発現場へと行くことになったのですが、僕でもわかるようなやばいような事がかなりゴロゴロあって唖然とする毎日です(運が良いのか悪いのか…)

今日はそんな中の一つを紹介したいと思います


#R無しRDB
これには本当にびっくりしました
どういうことかというと、**外部キーをひとつも使ってなかったのです**

分析系DBなのかと思いきや調べたり聞いたりして確認したところがっつり処理系、しかもコアな部分…ｗ
データの不整合を許せない部分なのに外部キーを全く使っていないという、アンチパターンというか呆れパターンというか…

###何が悪いの？？
そう、まずはここから説明していきます
同じことを繰り返さないようにするための記事なので、ただバカにするだけだと意味ないですからね

1980年代～1990年代くらいに過激な生き残りをかけたDB戦争があったらしいです(ギリ生まるかどうかくらいなのでよく知らないｗ)

その過激な戦争を勝ち抜いたのが**RDB(リレーショナルデータベース)**でした
Excelの表のような構造でデータを取り扱うことが特徴です
これによって他のDB群を一蹴した訳ですね

と、ここまではちょっとRDBを触ったことがある方なら知っているんじゃないかなと思いますが、こっからです！！！

**RDBの最大の利点はリレーションシップを張れることです！**
ちょーかんたんに言うと、外部キーを付ける、ということです

リレーションシップを張ることにより、DBに格納されるデータをRDBMSが事前にチェックすることができるようになります

図を書いてみました![RDBMS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/60b16c22-2aee-d606-d5f9-853741028539.png)

アプリくんはとにかくデータをDBに保存したいのでなんでもかんでも適当に持ってきちゃいます
DBはただの倉庫なので、誰もいないと間違ったデータもそのまま入ってしまいます
そこでRDBMSくんの出番です
アプリくんが持ってきたデータをチェックして、DBに保存できるかどうかを確認します
ルール違反の場合はアプリくんにエラーを渡します
つまり、RDBMSくんは**倉庫番**みたいな感じなんです

このルールには主キー制約、チェック制約、NOT NULL制約などありますが、その中でも**外部キー制約はめちゃくちゃ強力です**

主キー制約はひとつのテーブルの中でユニーク(一意)であることを保証できますが、これだけだと複数のテーブルに同じ意味を持ったデータを持つときにそれぞれのテーブルでデータが統一されていない、ということが発生します

外部キーはこのバラバラのテーブルに散ってしまった同じ意味を持ったデータを紐づけます

**<font color="Red">つまり、RDBにおいて外部キーを使わないということはデータの不整合を受け入れる、ということなんです！！！</font>**

###原因
なぜこんなことが起こってしまうのか…
僕なりに原因っぽいものを探してみました

- 外部キーってなんかよくわからんけどめんどくさくね？
- 時間がないから適当に作った
- joinを使うとパフォーマンスが悪くなるからテーブル分けなかった
- クエリーがシンプルになるように目的別にテーブルを作った

こんなとこでしょうか…
上の2個はここまでの解説で外部キーの重要性について理解してもらえれば今後起きないかなと思います
悪いのは下2個です

>joinを使うとパフォーマンスが悪くなるからテーブル分けなかった

パフォーマンス重視マンは結構いますよね
この意見は本当に正しいでしょうか？

答えは**NO**です

RDBというのは複数のテーブルにまたがってデータの整合性が取れる、というのが利点でした
では、本来分けるべきテーブルを分割しなかったらどうなるでしょうか

**拡張性と柔軟性が死にます**

テーブルを分ける、というのはDBの拡張性と柔軟性を上げ、運用をしやすくなり、目的のデータを素早く取り出すことに繋がります
かんたんに言うと、テーブルを分割することで**DBの寿命が延びます**

ただ、これには例外もあります
最初のほうに出てきた分析系DB、というものがこれにあたります
データの整合性を捨てて、データの抽出に極振りしたDBのことです
RDBでも分析系DBは作れるのですが、NoSQLと呼ばれるDB群が結構流行ってますね

>クエリーがシンプルになるように目的別にテーブルを作った

クエリーは簡潔に書くべきです
今後紹介しようと思っているのですが、無駄に複雑なクエリーはメンテナンスもしずらい上にバカみたいに遅いです
**ですが、クエリーを中心に考えるべきではありません**

あくまでも中心はDBであり、クエリーというのはデータ頂戴と聞きに行ってるだけです
極端に言えば、クエリーがいくら長くて複雑でも、**早くデータを取り出せればそれでいいんです**

ただ、これにはもっと深い問題があります
<font color="MediumSlateBlue">アプリケーションが見るDBの構造と、DBの内部構造をごっちゃにしちゃってませんか？</font>

分析系DBとまでは言わなくても、View等を使ってアプリケーションが取り出しやすい形にしてあげることも重要です
SELECTの回数が非常に多いテーブルがある場合にはこの方法は効果的です

実はただ分けるだけじゃなくて、場合によってはView等を使ってテーブルを合体させることも重要なんです

###解決方法
ここまでいろいろ言ってきましたが、やっぱり気になるのは解決方法ですよね
R無しRDBを使ってる人には是非見てほしいです

######拡張性と柔軟性を考えてテーブル設計をしよう！
これは当然ですね
テーブル設計がボロボロのDBは寿命が短いです
R無しRDBは寿命0分です
まあ、そもそもこれが出来てたら誰も困らないんですけどね…

######後からでも外部キーを付ける
R無しRDBだったらR付ければいいじゃん！という発想です
テーブル構造から変えるのってしんどいというか、実質無理みたいな部分もあると思います
ただ、<font color ="red">外部キー付けるだけならテーブル構造変える必要ってないんですよね</font>
後付けでもかなり効くのでこれはおすすめです
エラーが出なければ…


#まとめ
- なんでもいいから外部キー付けろ
- DBの寿命を気にしろ

R無しRDB、どれくらいあり得ないことなのか分かって頂けたでしょうか…
パフォーマンスやら使いやすさやらを過剰に求めていると、データの不整合を全く気にしないクエリー屋さんになってしまいます
DBを使うことがある人は、是非クエリー屋さんではなくDB屋さんになってください

※注意
リレーションとはテーブル間の関連を指すものではなく、テーブル自体のことを意味するか、もしくは同じテーブル内の列間の関係性を意味しています
R無しRDBと書いていますが、実際にはRあります(テーブル間の関係性のことをリレーションと思っていたのでこのネーミングになりましたｗ)
ただ、他に良い名前が思い浮かばないのでこの名前にしておきます


- [本当にあったやらかしDB設計シリーズ一覧](https://qiita.com/bouitengineer12/items/e63e5f7d6f628da11362)