こんにちは。株式会社システムアイのshivadyです。
アドベントカレンダー企画3日目の担当をさせていただきます。
まずはじめに簡単に自己紹介をさせていただきますと、システムアイに入社前に色々なシステム構築など携わり、RDBの考え方に強い偏見ある為、今回記載させて頂きます。
かなり偏見を加味しますが、少しでも今後の業務にも役に立つはず!という思いを胸に今回は私が思っている RDB の考えはこうするべきという記事にいたしました。
上記の通り、過去の実績での偏見なので、新たな知識や実務でのナレッジ等の取得を目的に来訪いただいた方には大変申し訳ないのですが、温かい目で見守っていただけますと幸いです。またコードの貼り付けは無いのでご勘弁を・・
RDBとは
「RDB」とは、表形式の複数データを関連付けて使えるようにしたデータベースのことです。
昔は以下の考えでした。
1. 綺麗なテーブル設計をしたい。
2. SQLをワンライナーでデータを取得したい。
3. 外部キー制約設定するのかっこいいな
などなど
とりあえず余分なカラムをやテーブルを作らずに、正規化しようにこだわっておりました
そんなこんなで仕事をしていく内に以下の問題点に遭遇。
1. 綺麗なテーブル設計をしたい。
例:
AデータでIDが100を持っている。
BデータでIDが100を持っている。
同じデータを違うテーブルで持つのはもったいないので、Aだけ取り込もう。Bは被っているので不要と判断。
→Bデータの方が更新が早い場合に、Aデータが来るまでフロント画面で使えない。
2. SQLをワンライナーでデータを取得したい。
例:
Aテーブルに1億レコードある、Bテーブルに100万レコードある。JOINして一発でレコードを返そう。
→テーブルに持っているキーが検索する条件によって、オプティマイザの判断でキーが変わってしまい性能が劣化。
3. 外部キー制約設定するのかっこいいな
例:
Aテーブルのデータは、Bテーブルのデータを消してから消すもの。
→ドキュメントがきちんと整備されていない中で、テーブル相関図をきちんと把握しないとテストデータが作れない。
問題点は以下で対策していくが更に問題点に直面する。
1. Aデータの到着を待たずにBデータで入れるようにするが、タイミングに寄ってはデッドロックに遭遇
2. INDEXを貼って性能を上げるが、今度はデータを入れる際にINDEX作成コストが上がってしまい、データ投入に時間が掛かり、検索結果の最新化が遅くなる。
3. テーブル相関図を作るが習熟コストが高いし、面倒。更にメンテを忘れる。
表形式の複数データを関連付けて使えるようにしたデータベースという事だったが、この関連付けてという言葉が罠だと気づいた。
まずは結論から言うと「RDB」の概念は以下と割り切るのが必要だと思います。(ここからは偏見です。きちんと整地化して利用している皆さんすいません。)
RDBとは
「RDB」とは、表形式のデータを使えるようにしたデータベースのことです。
1. データごとにテーブルを用意する。
2. SQLは出来る限りシンプル。JOINなど覚えないでいい。
3. 外部キー制約なんかいらない。
上記の考え方に基づくと二次被害まで出ていた問題が改善した。
前提:テーブルの正規化はしない
1. それぞれテーブルを用意し、取得タイミングはフロント側で判断をする。
2. SQL発行を2回に変えたら、INDEXが変わったので、足す必要がない。
3. 簡単にテストデータが作れる。
まとめ
色々と皆さんが今後 RDB でテーブル設計など実施する場合には、各データの関連性は気にせずに、存在するデータを入れる 表形式のデータ を入れる 箱 と考えて頂けるといいかなと思います。
多分以下のメリットがあると思います。(偏見まとめ)
- Modelの書き方が単体のテーブルだけのSELECTになるので、共通化しやすくなるはず。
- 簡単なSQLだけを覚えればいいので、習熟コストが少なくなる。(SELECTの記載を知っていればなんとかなる。)
- データベースの入れ替えが簡単になる。
- テーブル単位にサーバを分けるようになる。
- ビュー、ストアドを考えなくていい。必要な場合はワークテーブルとして新規に作成する。
- パーティショニング機能で性能が出る可能性が高くなる。
- EXPLAINの解析結果が簡単になる。(Nested-Loopを考えなくてよくなる。)
- コントローラー側でのプログラム処理に任せるので、プログラムを書いている感が増す。
JOINするSQLを書かずにシンプルにSQLを書く事がいいと個人的には思います。
余談
上記の考えのもと Olympic Data Feed を使ったテーブル設計し、無事にリオ五輪のサイト提供を実施出来たのは懐かしい思い出です。某Yのサイト、Nのサイトなどに載せてました。
ただ、DB(CloudSQL)をスレーブ20台構成(当時のGCP最大設定数)で直接参照などした場合に、コンテンツが返せなかったので RDB とはデータを入れる 箱 という考え方になりましたので、皆さんが今後システム設計する場合にデータベースの部分で何とか性能を出せるよう頑張ろうはしない方がいいと思ってます。あくまでデータを溜める箱というイメージで捉えていただければと思います。何卒よろしくお願いいたします。