Realmについて知る①

備忘録
#はじめに
Realmについて学習するために書き、前提としてiOSの利用で話を進めていく。

※[この本](https://www.amazon.co.jp/%E8%BB%BD%E9%87%8F%E3%83%BB%E9%AB%98%E9%80%9F%E3%83%A2%E3%83%90%E3%82%A4%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9Realm%E5%85%A5%E9%96%80-%E8%8F%85%E5%8E%9F-%E7%A5%90/dp/4774188484)と各サイトを参考にして学んでいく。

#そもそもデータベース(DB)とは？
`色んなデータを格納しているデータの集合体`。

基本的にアプリを完全に終了した場合、デメモリ上からータは消えてしまう。

例えば、TODOアプリで考えてみると、アプリ起動中に追加したタスクをDBに保存することによって`アプリ内にタスクというデータを保存する事が可能`になる。

また過去に保存したタスクを`効率よく検索できる機能`もDBには備わっている。

#iOSで用意されている保存方法
###・UserDefaults
キーと保存したい値のペアを簡単にアプリ内で永続化することができる`キーバリュー型のDB`。

plist形式(XMLファイル)で保存されている。
[.plistってなんやねん？](https://qiita.com/Howasuto/items/29f1db794925052b4e6d)

コードで書くとこんな感じ↓

```swift
import Foundation

// キーバリュー型のDB
let userDefaults = UserDefaults.standard

// キーと値
var key = "hogeKey"
var text = "hoge"

// 保存
userDefaults.set(text, forKey: key)

// 取得
var savedText = userDefaults.string(forKey: key) ?? ""

// 削除
userDefaults.removeObject(forKey: key)
```

#####○メリット
- 様々な型を保存・取得できるAPIが複数用意されている
- 純正のフレームワークなので簡単に使うことができる
- 学習コストが低い

#####○デメリット
- 自前で用意した型は保存できなくないが、少し工夫が必要
- 使用するには全てのデータをメモリに展開する必要があり、大量にデータを保存しているとメモリの負担が大きいため大量のデータ保存には不向き
- 検索機能はない

###・SQLite
アプリでの利用を想定されて作られたDBで非常に軽量。

詳しく書くと、SQLiteは`RDBMS(リレーショナルDB管理システム)の一つ`であり、`SQL(DB言語)`を使用して操作する。

#####○メリット
- 高速に動作し、様々な検索機能が備わっている
- オープンソース
- 他のDBでも使われているSQLを使用して操作可能

#####○デメリット
- SQLを書けないと操作できない
- 非同期処理や同時書き込みに対応するには、自分で制御・管理しなくてはならない

#####※DBMS(DB管理システム)とは
現実で例えると、DBが図書館、DBMSはそこで働く職員、SQLは日本語や英語など。

職員に「この本を追加してほしい」と頼めば新たに追加してくれるし、「この本はどこにある？」と伝えれば自分で探すよりも効率よく読みたい本を見つける事ができる。

下記のサイトを参考にすると、DBというのは`データベースファイル(データが書き込まれているファイル)　+ DBMS`の２つで構成されていて、このデータベースファイルにデータを書き込んだり読み込んだりしているのがDBMSだそう↓

※[DBとDBMS(DB管理システム)の違い](https://pyteyon.hatenablog.com/entry/2019/09/05/193000#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B)

#####※RDBMS(リレーショナルDB管理システム)とは
DBMSには階層型やネットワーク型といった様々な形式があり、その中でも主流なのが`関係(リレーショナル)型`。

大きな特徴として、`表(テーブル)`、`行(レコード)`、`列(カラム)`で構成されている。

`・表(テーブル)`
複数のデータ(レコード)を収容する場所。
![db_関係型_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/f5485ee1-cfd3-2038-1e95-88d0f0938631.png)

`・行(レコード)`
1件分のデータ。
![レコード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/e25e6c72-2284-2824-3856-cf3a9e0589d8.png)

`・列(カラム)`
データを構成する各項目。
![フィールド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/a4dc9bc8-8190-0788-1318-83e05ccde27b.png)

#Realmとは
モバイル向けに設計されたDB。

大きな特徴としては、`Swiftのクラスが、Realmでのテーブル定義`となり、そのクラスにRealm特有の`Objectクラス`を継承することによって、Realmでのテーブルとなる。

```swift
import RealmSwift

// Realmのテーブル定義
class　Hoge: Object {
  // DBで扱いたい値をプロパティで定義する
  @objc dynamic var hoge: String = "hogehoge"
  @objc dynamic var fuga: Bool = false
}
```
SQLiteでは、SQLでテーブル定義しなくてはならないし、それらをSwiftのオブジェクトとして扱うためのクラスも定義する必要がある。

しかし、RealmではSwiftでクラスを作れば、それがテーブルとなる。

#####○メリット
・[SQLiteや純正のCore Dataよりも高速](https://qiita.com/LyricalMaestro0/items/301a17b0026e9467c26b)らしい
・クラス定義がそのままテーブル定義となる
・自前の型も簡単に保存可能
・プライマリキーが指定できる

#####○デメリット
・オートインクリメントを設定できない
・[取得するデータの上限を設定するlimitがない](https://www.dbonline.jp/mysql/select/index12.html)

#####※プライマリキー(主キー)とは
`テーブル内でレコードを一意(重複しない)に識別することができるように指定される項目(カラム)`。

現実で例えると、ある学校の1クラスがテーブル、生徒がレコードで出席番号が主キーとなる。

イメージはこんな感じ↓
![スクリーンショット 2021-12-12 7.46.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/6a246f02-74e1-fcf9-b758-876ba73f85c5.png)
「出席番号」、「名前」、「性別」という３つの項目がカラムとなる。

どれでも主キーにできる訳ではなく下記の２つの条件を満たしてなければいけない。

1.`一意になっていること`
２.`nil(空)ではないこと`

以上のカラムが主キーとして指定できる。

先ほどのテーブルで言うと、「出席番号」は一意であり、必ず生徒が居れば番号が振り分けられるため主キーに適している。

#####※オートインクリメントとは
指定したカラムに対してデータが追加されると、`自動的に１ずつ値を付与してくれる機能`。

基本的にオートインクリメントは主キーと併用して使われる。

#おわりに
②はRealmの読み書き・削除なんかをまとめたい。

後はマイグレーションの事とか。

何か間違っていることや疑問があればコメントして下さると有り難いです。