0

約 2000 個のオブジェクトを返す非常に基本的なフェッチ リクエストを実行しています。batchSize が 15 の NSFetchedResultsController を使用しています。

    predicate= [NSPredicate predicateWithFormat:@"ANY tags.tagName==%@", currentTagObject.tagName];
    [fetchRequest setPredicate:predicate];

    NSSortDescriptor *sort= [[NSSortDescriptor alloc] initWithKey:@"createDate" ascending:NO selector:@selector(compare:)];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
    [fetchRequest setFetchBatchSize:15];
   self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"createDay" cacheName:nil];

ただし、フェッチ リクエストには 10 秒以上かかります。何が起こっているかを確認できるように、SQLite デバッグを有効にしました。2000 個のエンティティすべてをフェッチしていると思いますが、実際の値を持つのは 15 個だけで、何らかの理由で 2000 個のオブジェクトをすべて調べてフォールトします。

フェッチ中に、次の行が何千回も表示されます。

2012-06-22 21:14:47.546 app[9227:707] CoreData: annotation: sql connection fetch time: 0.0107s
2012-06-22 21:14:47.551 app[9227:707] CoreData: annotation: total fetch execution time: 0.0171s for 15 rows.
2012-06-22 21:14:47.568 app[9227:707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZAUTHOREMAIL, t0.ZAUTHORNAME, t0.ZCREATEDATE, t0.ZISGLOBAL, t0.ZISLOCKED, t0.ZISNEW, t0.ZISPENDINGDELETE, t0.ZISPENDINGSYNC, t0.ZLASTUPDATED, t0.ZLOCALLYMODIFIEDDATE, t0.ZMETALASTUPDATED, t0.ZNOTEID, t0.ZNUMBEROFCHILDREN, t0.ZPARENTAUTHOREMAIL, t0.ZPARENTNOTEID, t0.ZROOTAUTHOREMAIL, t0.ZROOTNOTEID, t0.Z4PENDINGADDNOTES, t0.Z4PENDINGREMOVENOTES FROM ZMBNOTEOBJECT t0 WHERE  t0.Z_PK IN  (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)  ORDER BY t0.ZCREATEDATE DESC LIMIT 15
...thousands more lines exactly similar to the three above

私のテーブルには一度に 5 つのセルしか表示されないため、すべてのオブジェクトがすぐにエラーになる理由がわかりません。何が原因でしょうか? テーブルをスクロールしなくても、すべてのオブジェクトがすぐにエラーになるのはなぜですか? おそらく反復されて、どこかでアクセスされている可能性がありますか? 呼び出しNSArray *fetchedObjects = fetchedResultsController.fetchedObjectsによって、すべてのオブジェクトに何らかの障害が発生する可能性がありますか?

4

2 に答える 2

0

表示される動作は、Core Data Programming Guide のBatch-faulting and Pre-fetching の段落で詳しく説明されています。

つまり、述語を使用して特定の名前のタグを持つオブジェクトをフェッチする場合は、タグ オブジェクトをプリフェッチする必要があります。これは、通常、オブジェクトをフェッチするとき、Core Data は関連するオブジェクトをフェッチせず、代わりにフォールトを使用するためです。これで、述語はこれらの障害を個別にトリガーしますが、これは遅いです。

于 2012-06-23T10:16:08.033 に答える
-1

batchSize(私の強調)についてのドキュメントでそれが何を言っているかをチェックしてください:

デフォルト値は0です。バッチサイズ0は無限として扱われ、バッチ障害の動作を無効にします。

ゼロ以外のバッチサイズを設定すると、フェッチの実行時に返されるオブジェクトのコレクションがバッチに分割されます。フェッチが実行されると、リクエスト全体が評価され、一致するすべてのオブジェクトのIDが記録されますが、一度に永続ストアからフェッチされるのbatchSizeオブジェクトのデータのみです。リクエストの実行から返される配列は、オンデマンドでバッチを透過的にフォールトするプロキシオブジェクトになります。(データベース用語では、これはメモリ内カーソルです。)

この機能を使用して、アプリケーションのデータのワーキングセットを制限できます。fetchLimitと組み合わせて、任意の結果セットのサブ範囲を作成できます。

したがって、明らかに、この説明によれば、店舗への往復は2000/15になります。それには確かに時間がかかります。ソートとANY述語のためにすべてのデータが必要ですが、一度に15個しか取得しないように要求に指示しました。

また、完全を期すために、前のコメントから:compareソート記述子からを削除します。

于 2012-06-23T09:08:58.830 に答える