#realm_jp 第8回 Realm meetupに参加してきたまとめ

公開日: 

前職の御師匠様の一人が登壇されるとのことを聞きつけて、8回目にして、Realmのmeetupに初参加してまいりましたのでその時のまとめです。

Recent Updates

  • 山崎誠さんがRealmのメンバーに加わりました
    • RealmでのJavaの開発や日本のサポートを担当します

Realm Java 0.84.0について

0.83.0

  • NULLプロパティ
  • 新しいファイルフォーマットになったので、開いた際に自動的にファイルフォーマットが変わってしまうので、一度0.83にしてしまうと0.82以前には戻せなくなります
  • 要マイグレーション
  • IntegerやLongなどのプリミティブラッパークラスのサポート
  • isNullなどのnullに対するクエリの追加
  • NULLに対応するために集計の変更があるので新しい関数を使うようにして下さい
  • 使う機会があまりないかもしれないがx86_64を正式サポート
  • Date型の表現できる範囲の拡大。ミリ秒は格納できないのは今までどおり。

NULLプロパティ(Java)

  • @Requiredが追加されて、値としてnullを許さないフィールドを定義することができるようになった
  • Integerなどのプリミティブラッパークラスを使えばNULLがいれられるようになる

NULLに対するクエリ

  • isNull(),isNotNull()が拡張

Migration

  • プロパティに@Requiredを指定すればマイグレーションせずにすむが、NULLいれられるようにするならマイグレーションをしないといけない
  • 既存のカラムをnullableにするにはconvertColumnToNullable()メソッドを使用する

0.84.0

  • 非同期クエリ・トランザクション:クエリ自体の結果を別スレッドで読み込めるようになった
    • データが多い時や複雑なクエリを発行するときは別スレッドでクエリが発行できるのでUI threadが邪魔されない
  • isEmpty(), distinct()のサポート
  • isClosed(), isInTransaction(), isValid()の追加
    • isClosed() : 閉じられているかどうか確認
    • isValid() : realmがcloseされていたり、オブジェクトが存在していなかったりするとfalseがかえったりする
  • RealmPrimaryKeyConstraintExceptionという例外が追加されて一意性制約の違反を簡単に気づけるようにした

非同期クエリ

  • 更新されたタイミングを知りたければリスナーを登録して取得もできる
  • on stopでとめないとメモリ的に困ることになる

非同期トランザクション

  • 非同期クエリと同じ感じ

開発中

  • RxJavaとNewMigrationAPIの検討をしている
  • Realmのモデルを操作する形でマイグレーションを実行するというのを進めている

Realm Objective-C/swift 0.96.2

0.96.0

NULLプロパティをサポート

  • プログラム側でnullを判断していたり、ラッパーしていたことをしなくてもするようになりました
  • ファイルフォーマットが自動的に新しくなるので一回開くと後戻りできなくなりますので注意
  • 数値のみのアプリケーションなどはマイグレーションの必要性はないが、例えばstringはnullableなカラムになるのでマイグレーションが必要になる
  • マイグレーションをしないようにするにはプロパティにrequiredPropertiesというのをつけるとnullableなカラムじゃないと宣言できる

コレクション・キーパス・クエリ

  • KVCと同じようなことができるようになりました
  • ブログのオブジェクトがあって記事ごとにコメントがあり、コメントが1件以上もっているものを抽出する場合は、今まで素直にかけなかったのが以下のように書けるようになりました

    realm.objects(Article).filter("comments.@count > 0")
  • クエリの左辺に書くものだけサポートされている
  • コメントの多い順に並べるのはできないのでコメントカウントみたいなカラムをもつしかない

エラーハンドリングの改善

  • コミットした時のエラーを今まではコミットした時に(IOのエラーやdisk不足など)クラッシュするしかなかったが、キャッチできるようになった
  • realmのデータを消してやり直すだけでいい時は便利な機能
  • コミットに失敗するのは重大な問題が起こっているので、データを消す以外の方法で復帰するのをおすすめしたい

0.96.2

  • Xcode7.1でビルド
    • 7.1を使ってcarthageなどでリンクできるようになりました
  • nullサポートでoptionalのプロパティを使った時にすぐにクラッシュしていたバグ等も直されてます

NULLプロパティ (swift)

  • obj-cのときは自動的にnullableになる
  • NSString, String, NSDate, NSDataについてはoptionalの構文を使えばnullableかどうかの区別がつく
  • nullがはいらないプロパティにNULLが入ってしまってもrealm側で弾かれます
  • IntやDoubleなどの型はoptionalだけではだめで、RealmOptionalという型を指定して使って下さい
    • 数値のtypeがoptionalでダメな理由は、realmは遅延ロード、高速なパフォーマンスを実現するためにオブジェクトのプロパティのメソッドを入れ替えており、アクセスがあった時だけはじめてデータを取りに来ているが、それを実現するためにdynamicにする必要がある。ただしこれができるのはoptionalじゃない型か、NSObjectにConverできる形だけ。そうしないとobj-cでプロパティが読み込めず動的に読み込めなくなるので、RealmOptionalを使う必要がある

NULLプロパティ(Obj-c)

  • NULLでないという指定をするときはrequiredPropertisというクラスメソッドを指定する
    • NULL以外がはいると保存する段階で弾かれる
  • NSNumberがFloatかIntかはクラス定義を読み込んで自動的に構築しているので、NSNumberをgenericsのようなかたちでRLMInt、RLMDoubleなどのように指定する必要がある

Migration

  • アップデートするとマイグレーションが必要という警告が出ます
  • requiredPropertiesに指定すればマイグレーションをしなくて済む
  • しかしこれくらいであればrealm側でオートマイグレーションしてくれます
    • スキーマのバージョンをあげるだけでOKです
  • マイグレーションの処理をブロックで渡すが、ブロックは空でOKです
    • もしデータを入れ替えるなどの処理を入れる場合はブロックに処理を書いて下さい

tvOS対応

  • 現在進行中
  • 制限として、書き込めるストレージがないわけではないが、すごい制限されている
    • CacheとTempしか書き込まれないので、次起動した時にファイルがあるかどうかの保証はされてない
    • しかしソートなどの賢いキャッシュとして使う分にはいいと思います。

その他

  • 非同期クエリは作業中ですが、まだ時間がかかりそうです。
    • javaとobj-cどちらも非同期クエリが有効なのは十数万件のデータに対して、たくさんのORを繋ぐようなときや、containsクエリを発行するときなど、処理に時間がかかるものをやるときに有効

FAQ

  • FineGrainNotification(何のデータが変わったかを通知するための仕組み)はどうなってる?
    • 進捗はまだない。おそらく年内には間に合わない
    • 1.0からは除かれるかもしれません
  • tvOSの最大容量はどれくらい?
    • 200Mは一つのアプリケーションの容量
    • Cache, tempにかくぶんには今のところ明言されている容量の制限はないが、次の起動時に残っている保証はない
    • developer kitで確かめる限りはどこまでも書き込めるし、wipeされることもない
  • 他にtvOSの面白い機能について
    • 禁止されたAPIもリフレクションすると動かせたりします
    • webviewを動かせたが、inputはできない

アプリ開発初心者によるRealm導入事例

アプリ開発初心者による
Realm導入事例 from Ryuji Watanabe

書きました

Realmを導入したアプリ

  • エキサイト翻訳
    • 過去のバージョンはSQLiteだったが、Clip機能でRealmを使用
    • 旧バージョンからコンバートするような処理が入ってます
  • 女子トピ
    • お気に入り、設定などでRealmを使用
    • 一人で3ヶ月位で作りました
  • E・レシピ
    • お気に入り、買い物リスト、アクセストークンの保存などでRealmを使用

導入のきっかけ/ポイント

  • 開発ペースに勢いを感じた
  • ドキュメントがわかりやすく、日本語でも提供されていた
    • 初心者だったので、英語よりは日本語のほうが吸収度が高い
  • 情報が多い
  • CoreDataより学習コストが低い
    • SQLiteよりも低いと思う
  • パフォーマンスがいい
  • SQL書かなくていい
  • やりたいことはサンプルコードに書いてある

開発中のエピソード

  • 女子トピ
    • 頑張ってCoreDataでやっていたがCoreDataの扱いに不安があったのでRealmにした
    • コードレビューをしていてRealmの簡単さに気づいた
  • E・レシピ
    • iOS9でキーチェーンが読み出せなくなる謎のバグがあったのでRealmの暗号化を使用した
    • アプリ削除しても問題なかったため使用した

苦労した点

  • 削除したデータをうっかりまた削除しようとするとCrushした
    • このデータが存在していないかどうかのフラグ(Object.invalidated)に気づくまでに時間がかかった
  • 特定のオブジェクトだけ暗号化ということができない
    • レアなケースだが、あると嬉しい
    • 暗号化する必要が無いものは別ファイルにわけて対応した
  • Realmのバージョンアップが頻繁にある
    • 1.0になってないし、swiftの進化もあるので許容範囲
    • できるだけ最新版を用い、最終テスト段階でロックしている
    • tryが入った時は少し泣きました
  • 開発中の構造変更
    • オブジェクトが変わったときにrealmを削除して対応するのだが、削除し忘れるとあれ?ってなることがあった。

今後の展開

  • 扱いやすいので他アプリでもSQLiteからRealmに移行させたい
  • マイグレーション
    • すこし心配はしているがみたかんじは簡単そう
  • APIのキャッシュなどに使用
    • キャッシュにするならInMemoryにのっているものを使ってみたい
  • Android版ではRealmを使っていないので、布教する

おまけ

  • 10万件の乱数を登録し、ソートを行ってみた
SQLite Realm Realm (In-Memory)
iPhone6s plus 1.2sec 2.2sec 2.1sec
iPod touch 5G 9.2sec 15.8sec 15.6sec
  • InMemoryがあまりはやくならんかった。オブジェクトを作る時のオーバーヘッドが高い・・・?
  • 岸川さん曰く、仕組み的にファイルを使った場合とInMemoryとではあまり変わらない
    • InMemoryでも何らかのファイルが作成されている
    • InMemoryはdiskとsyncする過程が飛ばされる程度しかない
    • ファイルを使っていても全部on memoryな感覚です。

総括

  • 新規アプリを作る場合は、とくにはまることなく使えたので、積極的に検討する価値がある
    • 使った部分が標準的な機能のみだったので最短で導入できた鍵
  • 既存アプリでもrelamに移行する場合は、影響範囲の少ない箇所から移行すると良さそうだが、コンバートの手間や、徐々に変えてくうちにマイグレーションが発生するので、そのへんのコストを見極めた上でやらなければいけない
    • 全部移行できれば天国になれそう
  • 驚くほど簡単に導入できた!!!

FAQ

  • coredataで不安な点とは?
    • コードが長くなるので、合ってるのかどうか不安になる
    • 社内でcoredataで使える人がほとんどいない
    • 今後バージョンアップする時に困る
  • フレブルでrealm入れないんですか?
    • 開発止まっているが、やるとしたら入れます

日経電子版アプリが高速化のためにやったこと

武市 大志様

日経電子版についての説明

  • 会員数
    • 有料会員は44万人超え
    • 無料会員は244万人
    • 未登録ユーザーは2000万UB
  • アプリについては、2015/4にサーバサイドはAWS、アプリも内製化にした
    • 2週間に1回のペースで改善を続けています
  • 画面は一覧と記事で構成されています
  • データについてはAmazon cloudfrontからjsonをzipに固めて取得している
    • ケースによってはAPIを叩いて取得することもある
    • 今日はアプリとCDNとのやり取り、その保存のお話

日経電子版アプリが遅かった原因(アプリ起動〜データ取得〜画面表示)

データ量が多い

  • 1日約900記事数と記事数が多い
  • 1記事あたりの項目数が多い
    • 見出し1,2,3、記事の公開日時,,,
  • 記事内の画像も最初にまとめて取得していた
    • テキストも画像も含めて32Mも取得していた!

ひも付けが多い

  • 第4階層まであったりと階層構造が非常に深い
  • 記事から先も更に関連記事や用語などのひも付けがあった

速くするためにやったこと

  • 取得するデータ量を減らす
    • 画像は表示する際に都度表示
    • 深い階層は表現しないことにして情報量を減らした
    • 使わないサイズの画像情報も取得しない
    • 32MB -> 4k~7kになりました
  • jsonファイルを複数に分ける
    • マスター+記事jsonになっていた形を一覧を表示するのに必要なマスターjsonデータと、各記事のjsonデータと分けるようにした
    • zipzapを使って解凍せずに、その時に必要なjsonデータだけを取り出すようにした
  • データの階層をフラットにする
    • 親記事、小記事、孫記事という関連をプロパティで親か、子か、孫かの情報を持つようにした
  • 取得フローの変更
    • CoreData -> Realmに移行
    • zipを取得 -> 一覧情報のデータを取り出してrealmに保存 -> 一覧から記事に遷移する時に記事データをrealmに保存

Realmのいいところ

  • CoreDataだと関連をつけたオブジェクトをまとめて500件ほど保存するとパフォーマンス劣化するがRealmでは関連付けても高速に動作する
  • テーブルの定義が不要

Realmのちょっと面倒なところ

  • nilが入れられない -> いれられるようになった!
  • スレッドをまたいでのオブジェクトの参照ができない
  • カスケード削除できない

短縮できた時間

  • iPhone4S/iOS7で、ある日の朝刊の取得時間が32秒から4秒になりました
  • おじさまたちを中心に驚きの声があがる!
  • 改善前
    • おじさま:次のアップデートなにがあるの?
    • 「データ高速化!!」
    • おじさま:ふーん。で、あとは?
    • (╬☉д⊙)
  • 改善後
    • おじさま:こんなに早くなるのか!!!!!111
  • 速く出来た時は快感!

まとめ

  • データ構造を変えることでの高速化
  • 時にはサービス要件を変えることも必要
  • Realmは速かった

FAQ

  • 1日のスケジュールは?
    • エンジニアは、10:00にきて18:00 19:00に帰る感じで、打ち合わせは週2回くらいだが、武市様は忙殺状態
  • なんで内製化に動いた?
    • 完全外注にしていたら、ボタン一個足すのに、要件定義して見積もって、社内稟議して・・・というフローで3週間かかったりと、開発のスピードがでなかったため内製化した
  • おじさまはどうやって説得したか?
    • お客さんのもんでるものを提供しないといけないのに、その体制ができてないのでダメなんじゃないかと延々と話した
    • コスパ考えてもそんな変わらないんじゃないか
    • 社内のプロダクトつくったほうが、愛着や理解も深まるのではないか
    • といって説得した
  • swift? obj-c?
    • obj-cです
    • リスクがあるなという判断でobj-cになりました
    • 紙面アプリのビューアーはswiftです
  • 以前のものからフルリニューアルした時にコードは全部捨てた?
    • 0から作りなおしました
  • 機能をいれるネタは豊富に湧いてるか?
    • インプットをどれだけ増やすかというところだが、アプリのレビューにすごい書かれる
    • 深津さんに見てもらって意見をもらったりしている
    • ユーザの声で出てこないところをどうすくいあげるかは、仮説を勝手に立てて小さく検証してみて、数字をみたりしている
  • 岸川さん曰く、realmはRDBMSとは異なっていて、関連や正規化などは気にせず、画面に合わせてデータ構造をくんでしまうのがオススメ
    • lazy loadのおかげでパフォーマンスを気にせずロードできます
    • 必要な構造のデータをそのまま保存するのがおすすめです

@mogmetの所感

realmを扱うのは初心者にも優しく非常に扱いやすい、日本語が充実しているというのがrealmが流行った要因というのをとても感じるmeetupでした。

今後、jsや.NETにも展開されるらしいのでもっといろんな言語でrealmが使えるようになると便利だと思いました。

ただ、null参照の考案は10億ドル単位の過ちとも言われるように、nullを入れることでのバグも色々でてきそうで個人的には少し心配です。

NULL比較するとインデックスとか使えなくなりますしね…使わないで済むならそのほうがいいなぁと思ったりしています。

日経さんのデータ取得周りの仕組みも聞けたのはとても良かったです。

zipで固めて取得するというのはキャッシュもしやすいですしとても良い方法ですね。

いろんな話が聞けてとてもいいmeetupでした!

最後にご師匠様の本の宣伝をひとつ。

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