2010年7月18日日曜日

Core Data パフォーマンスチューニング

Core Data (store type は、SQLite) のパフォーマンスチューニングについての覚書。

改善したいのは検索速度。インデックスを使っているつもりが、本当にインデックスが効いているか?ということを如何に調べるかがポイント。

まず、遅い部分のクエリが実際はどのようなSQL文かを調べる。
具体的には次のようにする。
Xcode プロジェクトの実行可能ファイルの該当ファイルをダブルクリックする。"引数"ダブの、"起動時に渡される引数"に、"-com.apple.CoreData.SQLDebug 1" と書く(Core Data Programming Guide: Core Data Performance 参照)。すると、コンソールにSQL 文が出力されるようになる。SQL 文中の、'?' はプレースホルダーで、実際は、何かの値が入る。
ここでは、調べたSQL 文をコピーしておく。

次に、sqlite3 コマンドを使って、 先程コピーしたSQL 文を実行してみる。'?' の部分は実際の値に入れ替えること。
実行してみて結果が正しく得られることを確認する。

最後に、インデックスが効いているかを見る。
sqlite3 コマンドで、以下のようにする。

sqlite> EXPLAIN QUERY PLAN SELECT ........;


結果、WITH XXXXX_INDEX と出力されると、そのインデックスが効いている。
ソートのインデックスが効いている場合は、WITH XXXX_INDEX ORDER BY と出力される。詳しくは、SQLite のドキュメントを参照。

自分の場合は、ソートが遅かったようで、WITH XXXX_INDEX ORDER BY と表示されるようにModel を調整すると、検索スピードが向上した。


最後に、気になったことをメモ。

Core Data で複合インデックスを表現する方法はない??と思われる。

抽象エンティティ内に、インデックスを張った属性を追加して、具象エンティティからその属性を使用する場合、ソート時にインデックスが効かない。この時のSQL 文を調べてみると、WHERE 句に、具象エンティティのID がAND で連結されていた。したがって、インデックスが効かなくなるようだ。

2010年7月14日水曜日

ひとつのXcode プロジェクトで、iPhone アプリとMac用コマンドラインツールをビルドできない!

Xcode 3.1 までは、iPhone 用アプリを開発していプロジェクトに、Mac用のコマンドラインツールをビルドするターゲットを作成できていた。こうしていた理由は、CoreData のモデルを共用したかったため。もう少し具体的には、データベース作成処理だけMacで行い、完成したデータベースファイルをiPhoneアプリで使用する、ということをしたかったため。

ところが、Xcode 3.2 にアップデートした後から、以下のエラーが表示されて、ビルドできなかった。。。

target specifies product type 'com.apple.product-type.tool', but there's no such product type for the 'iphonesimulator' platform

そこで、以下のように xcodebuild を使ってみたとこと、ビルドできた。(「iPhoneSDK開発のレシピ」を参考にしました)
% xcodebuild -sdk macosx10.6 -target target_name

Xcode 上でのビルドは無理かと諦めかけていたところ、以下のMLをみつけて無事解決した。
Apple Mailing Lists: Single Project with Mac and iPhone targets

Option キーを押しながら、画面左上のドロップダウンをクリックすると、すべてのSDK を選択可能になるようだ。

これがスマートな正解なのかはよくわかりません。