爆速な “Realm” は本番投入に値するか

はじめに

こんにちは! Couples事業部でAndroid版の開発をしている海藤です!
今回は最近話題のRealmについて書きたいと思います。Realmは動作速度が非常に高速な点が取り上げられがちですが、実際に本番稼働しているアプリに投入するためには、メリットだけでなくデメリットも考慮した上で総合的に判断をする必要があります。現在CouplesAndroid版ではRealmを使っていませんが、将来的に導入したいと考えています。それに先立って、まずは個人アプリで実際に本番投入してみてメリット・デメリットが見えてきたので、この場を借りてまとめてみたいと思います。

Realmとは?

Realmはオープンソースで開発されているモバイルアプリ向けのデータベースです。公式サイトに「Realm is a replacement for SQLite & Core Data.」とあるように、モバイルアプリ開発の現場では、何年も前に登場したSQLiteやCore Dataが未だに現役で使われており、それらを置き換えることを目的としているようです。大きな特徴として、SQLiteやCore Dataと比較した場合に非常に高速である点や、Android/iOSの両方をサポートしている点が挙げられます。この記事ではrealm-javaの0.87.0を対象としています。

メリット

高速な動作速度

Realmのメリットは何と言ってもその高速な動作速度ではないでしょうか。公式サイトにも主要なデータベースとの速度比較が掲載されています。そのパフォーマンステストについて少し詳細に見てみたいと思います。

インサート処理

1秒間に何件のレコードがインサート可能かどうかというテストです。SQLiteが9000件ほどに対して、Realmは20000件となっており、2倍以上高速という結果になっています。

benchmarks-android.001

カウント処理

10万件のレコードが存在するテーブルに対して、特定の条件にマッチするレコードのカウント処理を1秒間に何件捌くことが出来るかというテストです。Realmが9倍程度高速という結果になっています。

benchmarks-android.002

クエリ処理

条件にマッチするレコードを取り出すクエリを1秒間に何件捌くことが出来るかというテストです。Realmが7倍程度高速という結果になっています。

benchmarks-android.003

クロスプラットフォーム対応・ドキュメントが豊富

RealmはAndroid/iOS両方に提供されていて、両OSとも使い方はほとんど同じなため、AndroidもiOSも開発するという場合には学習コストを抑えることが出来ると思います。また、公式サイトを見れば分かる通り、ドキュメントが非常にしっかりしていて、万が一分からないことがある場合にはSlackで中の人に直接質問することも出来るなどかなりのサポート体制が整っています。

デメリット

モデルクラスにいくつか制約がある

公式ドキュメントにあるように、Realmでは以下のようにモデルクラスを定義します。

public class User extends RealmObject {

    @PrimaryKey
    private String          name;
    private int             age;

    @Ignore
    private int             sessionId;

    // Standard getters & setters generated by your IDE…
    public String getName() { return name; }
    public void   setName(String name) { this.name = name; }
    public int    getAge() { return age; }
    public void   setAge(int age) { this.age = age; }
    public int    getSessionId() { return sessionId; }
    public void   setSessionId(int sessionId) { this.sessionId = sessionId; }
}

Realmのモデルクラスには通常のJavaクラスとは違って以下のような制約があります。

  • Only private instance fields.
  • Only default getter and setter methods.
  • Static fields, both public and private.
  • Static methods.
  • Implementing interfaces with no methods.

開発を行う中でモデルクラスにメンバーメソッドを定義することがあると思いますが、Realmで扱うモデルクラスにはgetter/setter以外のメンバメソッドを定義することが出来ません。具体的にはデバッグ用途でtoString()をオーバーライドしたり、モデルクラスの更新処理としてupdate()を定義したりといったことが出来ません。この問題に関しては現在議論が行われており、将来的にこの制約はなくなる見込みです。

Cascade Deleteが出来ない

Cascade Deleteとは、SQLiteなどに実装されている親オブジェクトが削除された時にそれに紐付いている子オブジェクトを自動的に削除する機能です。Realmではオブジェクト間のリレーションを定義することは出来ますが、Cascade Deleteがサポートされていないため、SQLiteと同じことを実現したい場合には自前で実装する必要があります。

例えば、以下のように複数のArticleを持つCategoryがある状態を考えてみます。この状態で親オブジェクトとなるCategoryを削除する場合、SQLiteでは子オブジェクトとなるArticleを自動的に削除することが可能ですが、RealmではCategoryを削除してもそれに紐付くArticleは削除されません。

er-disgram

この問題に関しても現在議論が行われており、将来的にはサポートされる見込みです。

おわりに

今回はCouplesのAndroid版にRealmを導入するために色々と調べた結果をまとめてみました。最終的に現在利用しているActiveAndroidからの乗り換えコストが高い&Realm導入よりも優先度の高い項目があると判断し、CouplesのAndroid版では導入を見送ることになりました。しかし、Realm自体は以前と比べてかなり進化していて、新規開発では間違いなく採用候補に上がるのではないかと思います。

  • このエントリーをはてなブックマークに追加

Recommend

Tech Blogはじめます

Go Conference 2015 Winter でLTしてきました! #gocon