iOSアプリ開発者だからこそ知っておきたい、データベース論理設計の基礎

# はじめに
こんにちは、iOSエンジニアの [dayossi](https://twitter.com/dayossi) です。

家族が幸せになれるサービスを提供したいと思って、
[HaloHalo](https://hallo-hallo.sakura.ne.jp/home/)という家族日記アプリをリリースしています。

データベース設計を本格的に勉強しはじめて、
「ちゃんと勉強しとかないとまずいな」と感じたので
学んだことをアウトプットします。

# 本記事の視点

これまでドキュメント型データベースを扱ってきたのですが、
リレーショナル型データベースの考え方や扱い方が設計段階から違う点があったので

リレーショナル型データベースの論理設計段階のざっくりとしたポイントを押さえつつ、
アンチパターンがなぜアンチパターンなのかを考えたいと思います。

# そもそもデータベースってなんだ？

データベースは、情報を格納し、検索や更新など整理も容易にしてくれる箱のようなものです。

よく使用される ２つのデータベースを比較すると、以下のような特徴があります。

| データベースの大分類 | 詳細分類 | データモデルの特徴 | SQL使用 
|:-----------|:------------|:------------|:------------|
| リレーショナルデータベース |       | 行・列で構成される表構造   |使用する |
| NoSQL | key-value型<br>カラム型<br>カラムストア型<br>グラフ型<br>ドキュメント型   |  各詳細型によって異なる   | 使用しない |


例えば、AWSのRelational DataBaseはリレーショナルデータベースに、
FirebaseのCloud Firestoreは、NoSQLのドキュメント型にそれぞれ該当します。

今回は、リレーショナルデータベースにフォーカスしていきます。

# リレーショナルデータベース（RDB）の特徴

以下、リレーショナルデータベースを RDB と略して記載します。

RDBでは、行と列からなる表のようなデータ構造を持ちます。

| テーブル |  カラム1 | カラム2 | カラム3 |
|:-----------|:-----------|:------------|:------------|
| レコード1 |    |    |
| レコード2 |    |    
| レコード3 |    |    

類似したデータのまとまりをテーブル、縦の行をカラム、横の列をレコードと呼びます。

カラムには、同じ定義のデータが並び
レコードは、カラムごとのデータをまとめて閲覧できる構造となります。

| users |  user_id |  email | password | user_name | job
|:-----------|:-----------|:------------|:------------|:------------|:------------|:------------|
| レコード1 | 11111   |  hoge@.com  | HOGEHOGE |  ほげほげ | サーバーサイドエンジニア
| レコード2 | 22222   |  piyo@.co.jp | PIYOPIYO | ぴよぴよ | iOSエンジニア, Androidエンジニア
| レコード3 | 33333   |  fuga@.ne.jp | FUGAFUGA | ふがふが | デザイナー, SE

キーと呼ばれる、テーブル内のデータを個別に認識するカラムを
決めるのが一般的です。

上記の users テーブルで、user_id がキーとなっている場合
user_id は一意のものとして認識されます。

そのため、email や passwordなどが重複していても
user_id が重複していなければ一意のレコードとみなされます。

一意なデータの集まりであることを保証するため、
RDBでは正規化という作業を行います。

# 正規化のポイント

まず正規化の目的は、

> + 人間が理解できる形で、現実世界の事実を表現する
+ 事実の格納方法から冗長性を排除し、データの異常や不整合を防ぐ
+ 整合性製薬をサポートする 
([5](https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892)より引用)

正規化を行う際のポイントは、以下の5つです。

+ 行・列いずれも、順番は決まっていないこと
+ 値が同じ行は存在しないこと
+ すべての列は、値の型が決まっており、1つの値だけが入っていること
+ 値にテーブル内独自の意味をもたせない

先ほどの usersテーブルを、もう一度みてみます。

| users |  user_id |  email | password | user_name | job
|:-----------|:-----------|:------------|:------------|:------------|:------------|:------------|
| レコード1 | 11111   |  hoge@.com  | HOGEHOGE |  ほげほげ | サーバーサイドエンジニア
| レコード2 | 22222   |  piyo@.co.jp | PIYOPIYO | ぴよぴよ | iOSエンジニア, Androidエンジニア
| レコード3 | 33333   |  fuga@.ne.jp | FUGAFUGA | ふがふが | デザイナー, SE

jobの部分に複数の値が入っていますので、
ここは正規化を行うべき箇所となります。

| users |  user_id |  email | password | user_name | job_1 | job_2
|:-----------|:-----------|:------------|:------------|:------------|:------------|:------------|:------------|
| レコード1 | 11111   |  hoge@.com  | HOGEHOGE |  ほげほげ | サーバーサイドエンジニア |
| レコード2 | 22222   |  piyo@.co.jp | PIYOPIYO | ぴよぴよ | iOSエンジニア | Androidエンジニア
| レコード3 | 33333   |  fuga@.ne.jp | FUGAFUGA | ふがふが | デザイナー | SE

正規化は最大で5段階までありますが、今回は1段階目までにとどめます。

また、user_idが番号順に並んでいるように見えますが、
これは順番に整列するために保持しているのか確認が必要そうです。


RDBは、正規化された複数のテーブルを関連づけることで
以下のような個性を発揮します。

## 更新作業が早い

・関連のあるデータテーブルのキーを保持することで
 高速でデータを更新することができます。
　
 そのため、正規化とよばれる方法で
 一つのテーブルが肥大化しないよう、小さなテーブルに区切って関連づける作業が重要となります。

 また正規化を行うと、データが必ず一意であることも保証できるので
 メンテナンスも容易となります。

## 設計によって、検索に時間がかかることも

・一方、正規化を行うとテーブルを細分化したためにネストが深い構造となるため、
特定のデータを取り出したい場合は時間がかかることがあります。

・検索時には、関連づけられた複数のデータテーブルを
元の1つの巨大なテーブルにつなげ直す作業が内部で発生することがあります。

このデータテーブルをつなげ直す作業は負荷が大きいため、
頻発すると検索処理がどんどん遅くなっていきます。

正規化について一長一短があります。

ですが、そもそもデータが重複していては検索も更新も容易にできません。

もし正規化を行わなかった場合、データが重複したまま
データテーブルは大きくなっていきます。

結果、検索でも更新でもバグが発生しやすくなり、余分な時間がかかるリスクが残ります。

バグ発生のリスクを抑える正規化は行う前提で、
いかに検索もしやすいデータテーブルを設計するかがポイントとなります。

# まとめ

UserDefaultだと取り扱いにくい、APIレスポンスを保存する場合などで
RDBは威力を発揮してくれます。

RDBを操作する際はSQL言語が必要となりますが、
RealmなどSQLの取り扱いを簡単にしてくれるライブラリもありますので
iOSアプリ開発にも取り入れやすいと思います。

また、RDBとNoSQLのいいとこ取りである、[NewSQL](https://qiita.com/tzkoba/items/5316c6eac66510233115)なるものもあります。

NoSQLが注目されやすいですが、
企業ではまだまだSQLも活用されているので

ちゃんとデータベースの基礎も知っておくほうが
今後のために良さそうだなと思います。


# 参照・引用元とキーワード
情勢
1. [ついに刈り取られ始めたOracle Database](https://www.orangeitems.com/entry/2019/03/07/000500)

データベース：
2. [NoSQLの比較・ランキング・おすすめ製品一覧](https://www.itreview.jp/categories/nosql#category-description)
3. [【3分解説】データベースの種類とは？ (リレーショナル型データベース)]
(https://kino-code.com/what-is-kind-of-database/#toc6)
4. [【3分解説】データベースの種類とは？ (key-value型データベース)]
(https://kino-code.com/what-is-kind-of-database/#toc6)
5. [SQLアンチパターン](https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892)
6.  [2020年現在のNewSQLについて](https://qiita.com/tzkoba/items/5316c6eac66510233115)