5

アプリに非効率性があり、それを理解して修正したいと考えています。

私のアルゴリズムは次のとおりです。

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object

スキーマの一部である関連オブジェクトのキーを使用して述語クエリを作成することにより、A 行と B 行をチェックしています。A (常に) と B (実行がその部分に分岐した場合) の両方が、次のような SQL 選択を生成することがわかります。

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.

クエリの 0.0071 秒は 3GS デバイスでは問題ありませんが、これらを 100 追加すると、700 ミリ秒のブロッカーが得られます。

私のコードでは、これらのフェッチを行うためにヘルパーを使用しています。

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}

これは間違っていると思うので、別の方法でチェックを行う必要があります。データベースに一度だけヒットし、その後はメモリから取得する必要がありますよね? (SQL は、確実にローカルに存在し、以前のクエリでメモリにロードされているはずのオブジェクトに対しても実行されます。) しかし、外部ソースからの myObjectId しか持っていない場合、これは私が考えることができる最高のものです。

したがって、おそらく問題は、myObjectId (MyObject の Core Data int64 プロパティ) がある場合、関連するローカル オブジェクトが CD ストアに存在するかどうかを正しく確認するにはどうすればよいでしょうか? 可能な一致のセット全体をプリロードしてから、ローカル配列を述語しますか?

(考えられる解決策の 1 つは、これをバックグラウンド スレッドに移動することです。スレッドから変更を取得して [moc mergeChangesFromContextDidSaveNotification:aNotification]; を実行する場合を除いて、これは問題ありません (通知によってバックグラウンド スレッドから変更されたオブジェクトを取得する)、これはそれでもブロックします。)

4

6 に答える 6

9

Core Data Programming Guide の「Implementing Find-or-Create Efficiently」をお読みください。

基本的に、名前のような ID やプロパティの配列、または管理対象オブジェクト エンティティから取得したものを作成する必要があります。

次に、この配列を使用して管理対象オブジェクトをフィルタリングする述語を作成する必要があります。

[fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(objectID IN %@)", objectIDs]];

もちろん、「オブジェクト ID」は、識別に使用できるものなら何でもかまいません。NSManagedObjectID である必要はありません。

次に、フェッチ リクエストを 1 回実行し、フェッチされた結果のオブジェクトを繰り返し処理して、重複を見つけることができます。存在しない場合は、新しいものを追加します。

于 2010-02-05T20:04:43.997 に答える
3

すべてのオブジェクトに対して 1 つのフェッチを実行する必要がありますが、オブジェクトのサーバー ID のみをフェッチする必要があります。

setResultType:を に設定してsetPropertiesToFetch:を使用します。NSDictionaryResultType

于 2010-02-05T19:34:39.247 に答える
3

おそらく、メール クライアントから教訓を得ることができるでしょう。

これらは、最初にメッセージ ID のリストをサーバーに照会することによって機能します。クライアントがそのリストを取得すると、ローカル データ ストアと比較して、何かが異なるかどうかを確認します。

違いがある場合は、いくつかのアクションのいずれかが実行されます。1. クライアントには存在するがサーバーには存在せず、かつ IMAP である場合は、ローカルで削除します。2. サーバーには存在するがクライアントには存在しない場合は、残りのメッセージをダウンロードします。

あなたの場合、最初にすべての ID をクエリします。次に、フォローアップ クエリを送信して、まだ持っていないデータのすべてのデータを取得します。

レコードがローカルに存在する可能性があるが、サーバーでの最後のダウンロード以降に更新されている可能性がある場合、クエリには最終更新日を含める必要があります。

于 2010-02-05T18:02:15.813 に答える
1

何年もの間この同じ問題と戦った後、私はついにそれを完全に解決したこのブログエントリに出くわしました(そしてボーナスとして再利用可能なコードブロックです!)。

http://henrik.nyh.se/2007/01/importing-legacy-data-into-core-data-with-the-find-or-create-or-delete-pattern

コードサンプルはネットワーク部分をカバーしていませんが、NSDictionaryにロードするだけです。次に、これはローカルCoreDataコンテキストの同期を処理します。

于 2010-02-18T05:02:45.550 に答える
1

必要なのは、メモリにロードされるか、永続オブジェクト ストアよりもすばやくアクセスできる場所に格納される NSManagedObjectID の NSSet のようです。

こうすることで、ネットワークからのオブジェクト ID とキャッシュからのオブジェクト ID を比較でき、大きなデータ セットに対してフェッチ リクエストを実行する必要はありません。

マネージド エンティティ クラス内の -awakeFromInsert 内から ID をキャッシュに追加することはできますか?

于 2010-02-05T18:24:25.357 に答える
0

回答ではありませんが、「データの効率的なインポート」ドキュメントへの更新された URL

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW1

于 2011-04-17T00:41:29.937 に答える