■キャッシュ無し vs キャッシュ有り
executeFetchRequest:error: メソッドを用いて、 Entityのプロパティで一件だけ絞り込んで返すようなクエリは大変遅いということが分かりました。Indexを付けて実行してもほとんど速くなりません。どうやらそもそもバックエンドに使っているSqliteが大変遅い、特にコネクションを生成したり破棄したりするのが遅い感じがするので、ループで一件ずつ取得するなどのときはたくさんのSQLが実行されないようにする必要があります。 objectWithID: メソッドは試していないのでちょっと不明です。
回避策として、アプリが起動したタイミングで当該エンティティの全オブジェクトをあらかじめ取ってきて、 NSMutableDictionary にでも突っ込んでおく。次回以降のフェッチはその NSMutableDictionary から行う、と言うようにすると凄く速くなりました。
実測値は以下の通り。
pre loading time というのが自前のNSDictionaryキャッシュの事前生成、parseResponseBodyというのがXMLの解析で、この中に大量のCore DataオブジェクトをDBから引っ張ってくる処理が含まれています。
////////////////// プリキャッシュなし ////////////////// 2010-05-25 12:11:37.254 FetchAllModelA parseResponseBody time : -1.214856 2010-05-25 12:11:39.674 FetchAllModelB parseResponseBody time : -2.416063 2010-05-25 12:11:41.097 FetchAllModelC parseResponseBody time : -1.384185 ////////////////// プリキャッシュあり ////////////////// 2010-05-25 14:12:14.788 pre loading time : -0.039540 2010-05-25 14:12:17.518 FetchAllModelA parseResponseBody completed. time : -0.836754 2010-05-25 14:12:20.719 FetchAllModelB parseResponseBody completed. time : -1.312910 2010-05-25 14:12:19.169 FetchAllModelC parseResponseBody completed. time : -0.902832ほんの0.03秒のプリキャッシュ処理のおかげで、XML解析が最大で1秒以上短縮できています。とにかくCore DataがSQLを飛ばさないように調整すると効果があるみたいです。
■DB書き込み速度
NSManagedObject の生成はメモリ上 (NSManagedObjectContext) で行われるためなかなか高速なのですが、それを save するのがとにかく iPhone 3G で顕著に遅く、 300件程度のデータを保存するのに5秒以上かかってアプリが正常終了できないという事態が発生しました。リレーション張りすぎたかなーと思います>< iPhone 3GS なら2秒3秒程度で間違いなく完了するので特に問題になっていません。対策としては暇なときに逐一DBにsaveするか、どうでもいいデータはiPhone 3Gでは保存しないとか、一時エンティティにするとか。