0

我正在运行一个非常基本的获取请求,它返回大约 2000 个对象。我正在使用批处理大小为 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 不会获取相关对象,而是使用故障代替。现在,您的谓词触发单独触发这些故障,这很慢。

于 2012-06-23T10:16:08.033 回答
-1

查看文档中关于batchSize(我的重点)的内容:

默认值为 0。批量大小为 0 被视为无限,这将禁用批量故障行为。

如果设置非零批量大小,则执行提取时返回的对象集合被分成多个批次。执行 fetch 时,会评估整个请求并记录所有匹配对象的身份,但一次不会batchSize从持久存储获取对象的数据。执行请求返回的数组将是一个代理对象,可以根据需要透明地对批次进行故障处理。(在数据库术语中,这是一个内存游标。)

您可以使用此功能来限制应用程序中的工作数据集。结合 fetchLimit,您可以创建任意结果集的子范围。

所以,很明显,根据这个解释,你有 2000/15 次往返商店。这肯定需要一些时间。由于您的排序和ANY谓词,您需要所有数据,但您指示请求一次只能获取 15 个。

另外,为了完整起见,从前面的评论中:compare从你的排序描述符中删除。

于 2012-06-23T09:08:58.830 回答