iOS/Androidで使用できるDBMS(+ORM)であるRealmのイベント、Realm Tech Talk with JP Simard #1(於 freee株式会社さん)に行ってきました。
Tech Talk with JP Simard from Realm
Realmのメンバー、JP SimardさんによるRealmの紹介。
Realmの特徴
- オープンソース(ASL 2.0)である。なお、現時点でDBのCore部分はまだクローズドだが、オープンにする方向で進めている。
- iOS/Androidで同じように使用できる。リリースタイミングのずれはあるが*1、双方、同じ機能を提供する。
既存DBMS(およびORM)との比較
- iOSのCore DataはSQLiteのORM(Object Relational Mapper)で、古く、遅い。学習コストも高い。
- SQLiteは早いが、ORMでなくSQLクエリで操作する必要がある。スレッドセーフでない。
- ほか、FMDB(SQLiteのラッパー)などもあるが、総じて遅い。またAndroid向けには選択肢が少ない。
- ベンチマーク
モデルの定義
RLMObject
を継承したValue Objectを定義する。
@interface Employee : RLMObject
@property NSString *name;
@property float salary;
@end
RLM_ARRAY_TYPE(Employee)
@interface Company : RLMObject
@property NSString *name;
@property RLMArray<Employee> *employees
@end
これで、Employee
テーブルと、Employeeの配列(内部的にはrelation)を持ったCompany
テーブルができる。Swiftではデフォルト値の定義も可能。
(コードはその場でメモした擬似コードなので注意)
使いかた
Add(insert)はこんな感じで可能。
let employees = List<Employee>()
let company = Company()
Realm.write{ //transaction
defaultRealm.add(company);
}
GCDから使う場合
dispatch_async(queue){
realm.beginTransaction()
...
realm.commitWriteTransaction()
}
(※コードはイメージです)
抽出クエリは、#filter()
をチェインしていく形式で記述。
マルチスレッドでRealmを使っても、ちゃんと捌いてくれる。ただし、クエリで取り出したインスタンスはそのスレッドでしか使用できない。別スレッドでは再取得する必要があるので注意。
Notifications
例えばinsertされたタイミングで指定メソッドの呼び出しを登録できる。何がinsertされたかは(今は)わからない。
注意点
- NSDataは、秒単位までしか保持されない。これはAndroidとの整合性のため。ミリ秒以上の精度はNSTimeintervalを使う。
- KVOは未サポート
Work In Progress
- multi process
- fine-grain notifications(Notificationで操作されたオブジェクトも通知できる)
- async queries
- cascading deletes(リレーションのレコードを連鎖で削除する)
- nullable types(現状はNullを入れられない)
- sync
- open source core
質疑応答
理解できたものだけ。
- Realmのファイルは、iOS/Androidで共通フォーマットなのでファイルコピーで共有できる
- desktop appで、Realm Browserというのがある。CUIツールは無い
- coreは、TightDB(旧社名?)
- in memoryで利用するには、begin transactionのとき指定できる
- 若干パフォーマンス出ないかも?
- 【2/22追記】テストまわりとin memory storeの詳細はこちらを参照してください: Realm(realm-cocoa)を使うアプリをテストする #realm_jp - やらなイカ?
- arrayのcountをクエリで取ることはできない(カウントを格納するプロパティを設けるなどのwork around)
realm-javaを使ってみての発表
Chatwork 宮下さんの発表。ChatworkのAndroid版で実際に使用したお話。
Android のORMはそもそも選択肢が少ない。
- greenDAO: 早いけど準備が面倒
- ActiveAndroid: insertが遅い(Chatworkさんの事例での話で、大量にinsertが発生すると厳しい)
- Benchmark: 619件の処理(insert?)で、ActiveAndroidでは1551ms、Realmは414ms。
realm-javaでのモデル定義例
class xxx extends RealmObject{
@primaryKey private long id;
}
- RealmObjectはvalue objectでなくてはならず、ロジックは持てない。toString(), equals()とかもオーバーライドできない。
- Realmのobjectは、スレッド単位でしか利用できない。別スレッドで扱うならqueryしなおす
- 日本語ドキュメントのバージョンは0.72、最新は0.79.1。かなり変更があるので、最新情報にあたるほうがいい。
- ButterKnifeと干渉するところがあったが、Gradleの定義で回避できた
所感
iOS/Androidで共用できるシリアライズ機構としては、Dropboxが公開しているmx3も気になっているのですが、こちらはライブラリでなく実装サンプルであり、ORMも含めて考えるとRealmの有望さを感じました。
モデルがvalue objectに限定されることは不便に思いますが、ロジック付きのラッパーを作ればいいので致命的ではなさそう。
最近、DBMSを使う系のアプリを作っていないのですが、止まっている電エースアプリのAndroid版ででも使ってみたい。
懇親会では、freeeさんの会社およびプロダクト*2の話をたくさん聞けて、それもまた色々参考になりました。
freeeさん、岸川さん、通訳を買って出てくださった北さん、そしてJPさん、ありがとうございました。