RealmとSQLiteのパフォーマンス検証を行った話

データベースを使ったアプリを作る時、データベースとしてRealmを使うか？SQLiteを使うか？と迷う時があると思います。今回はどちらを使ったほうがいいか判断するためRealmとSQLiteでパフォーマンスに差があるのかの検証を行いました。

# 各データベースの説明
## SQLite
昔からあるモバイル用データベースシステム。典型的なRDBタイプなので、Oracle,MySQL, Postgreなどに慣れていれば割とさくっと使えます。AndroidではこのDBを使うためのAPIが標準で搭載されています。(SQLiteまわりは実はAndroidバージョンによるAPIの変化が激しくないという…)

## Realm
最近話題の次世代モバイルデータベースシステム。NoSQLタイプなので割と新しく学ぶことが多めな感じがあります。このRealmの強みは…
・APIが使いやすい！
・速い！
ということです。

Realmの公式ページは
https://realm.io/jp/
です。ここを見ればライブラリのダウンロード方法・使い方などが記載されています。

# パフォーマンス検証に使った環境
##プログラム
今回パフォーマンス検証に使ったプログラムはこちらに置いてあります。
https://github.com/LyricalMaestro/RealmBenchmark

このプログラムでは
・一括レコード追加
・全レコード一括読み込み
・10レコード読み込みクエリを100回実行
・全レコードクリア
の速度を測っています。

## 端末・データ数
端末は以下のものを使用しました。
・SHARP AQUOS PHONE SHV32(Android5.0)
・Google Nexus7(2013) (Android6.0)

今回はレコード数300, 2000, 20000, 200000, 1000000でやりました。

# 検証結果
実際に検証した結果を表にしてまとめます。
表内の数値の単位はmsです。

## 一括レコード追加
・SHARP AQUOS PHONE SHV32(Android5.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|72|     86     |
|     2000件|202|    236    |
|    20000件|1319 |    1825     |
|   200000件|20602 |     31657      |
|  1000000件| 114039 |    138059    |

・Google Nexus7(2013) (Android6.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|239|122|
|     2000件|392|  378|
|    20000件|3117|    2943 |
|   200000件|31282|   28601 |
|  1000000件|159635|  145559   |

RealmとSQLiteであまり差がないです。
端末によってはSQLiteの方がパフォーマンスがよいです。

## 全レコード一括読み込み

・SHARP AQUOS PHONE SHV32(Android5.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|23|9 |
|     2000件|37|  47 |
|    20000件|888| 1388|
|   200000件|10524| 14505 |
|  1000000件|55484| 134998   |

・Google Nexus7(2013) (Android6.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|16|9|
|     2000件|79|67|
|    20000件|947|2035|
|   200000件|11246|29701|
|  1000000件|59429|183853|

レコード数が数万以上になってくるとRealmの方がパフォーマンスがかなりよくなります。しかし、数百程度ではSQLiteの方に軍配が上がっています。

## 10レコード読み込みクエリを100回実行

・SHARP AQUOS PHONE SHV32(Android5.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|41|195|
|     2000件|95|293|
|    20000件|532|1446|
|   200000件|1361|14315|
|  1000000件|11255| 73001 |

・Google Nexus7(2013) (Android6.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|61|169|
|     2000件|68|250|
|    20000件|163|1104|
|   200000件|1163|11474|
|  1000000件|6678|56666|

これは圧倒的にRealmの方がパフォーマンスがいいですね！

## 全レコードクリア

・SHARP AQUOS PHONE SHV32(Android5.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|11|12|
|     2000件|11|11|
|    20000件|30|18|
|   200000件|36|213|
|  1000000件|101|868|

・Google Nexus7(2013) (Android6.0)

|           | Realm        | SQLite |
|----------:|------------:|------------:|
|      300件|12|14|
|     2000件|17|16|
|    20000件|20|23|
|   200000件|35|110|
|  1000000件|147|472|

やはりこれも数万レコードを超えるとRealmの方がパフォーマンスが良くなります。
…とはいえ上記３つの検証内容と比べるとかかった時間が1秒も満たなかったりするのでここはさほど気にするところではないかもしれません。

## 検証結果から言えること
・RealmはInsert系の処理はさほど強くはないが、大量のレコードを読み込んだりする処理に関してはものすごいパワーを発揮するということが言えます。また少量だけど大量のレコード読み込みクエリを多くさばくのにもものすごく長けています。

# 考察
大量のデータからレコード読み込む処理が多いアプリではRealmを採用したほうがパフォーマンスを発揮すると思います。特に一覧画面などの項目を読み込む処理では「１回のクエリでDBからデータを読み込むレコード数は多くはないが、検索内容変更による一覧更新などでクエリをばかばか投げる」ので、まさにもってこいのテクノロジだと思います。
あと、コードの書きやすさは断然Realmだと思いました。SQLiteで必要だったSQLiteOpenHelperの派生クラスの実装がいらないことと、ORMapper使わないと実装が楽にならないというしばりから解放されるのが強いと思います。そういう意味では可読性・生産性的な意味でも有利だと思います。

しかし、このRealmは執筆時点ではまだ0.86.1ということでベータ的な位置づけということで今後仕様が変わっていくこととSQLiteとはコードの書き方がだいぶ違うので、学習コストという意味では結構バカにならないかもしれないので（新しいライブラリを試して自分のものにすることに慣れている人はそこまでコストとは感じないと思いますが、そういうことに慣れていない人はかなり時間がかかるかも）数百程度のデータしか扱わない、かつプロジェクトの制約上時間がないのであればSQLiteでつっぱしるのもありかもしれません。

ちょっとRealmに対する否定的な内容も記載してしまいましたが、とにかく結論としては**Realmを使ったほうがメリットが大きい！**ということです。