Core data 核心数据以块的形式在fetchrequest上迭代,setFetchLimit只处理一半记录

Core data 核心数据以块的形式在fetchrequest上迭代,setFetchLimit只处理一半记录,core-data,batch-processing,nsfetchrequest,Core Data,Batch Processing,Nsfetchrequest,我试图以一定大小的块(batchSize)处理很多对象。这个循环似乎有效,但它只处理一半的记录。相关代码为: { //Prepare fetching products without images in the database NSFetchRequest * productFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Product"]; //Sort by last changed photo first NSS

我试图以一定大小的块(batchSize)处理很多对象。这个循环似乎有效,但它只处理一半的记录。相关代码为:

{
//Prepare fetching products without images in the database
NSFetchRequest * productFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Product"];

//Sort by last changed photo first
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"photoModificationDate" ascending:NO];
[productFetchRequest setSortDescriptors:@[sortDescriptor]];

NSPredicate *predicate = [NSPredicate predicateWithFormat: predicateString];
[productFetchRequest setPredicate:predicate];

//First get the total count
NSUInteger numberOfProducts = [self.backgroundMOC countForFetchRequest: productFetchRequest error: &error];
NSLog(@"Getting images for: %d products", numberOfProducts);

//Then set the batchsize to get chunks of data
NSUInteger batchSize = 25;
[productFetchRequest setFetchBatchSize: batchSize];
[productFetchRequest setFetchLimit:batchSize];

//Fetch the products in batches
for (NSUInteger offset = 0; offset < numberOfProducts; offset += batchSize) {
    @autoreleasepool {
        [productFetchRequest setFetchOffset: offset];
        NSArray * products = [self.backgroundMOC executeFetchRequest:productFetchRequest error:&error];
        NSLog(@"Offset: %d, number of products: %d", offset, [products count]);
        if (!products) {
            return NO;
        }

        for (Product * product in products) {
            NSLog(@"Downloading photo for product: %@", product.number);
            [self downLoadAndStoreImageForProduct:product];
        }
        [self saveAndResetBackgroundMOC];
    }
}

return YES;
{
//准备获取数据库中没有图像的产品
NSFetchRequest*productFetchRequest=[NSFetchRequest fetchRequestWithEntityName:@“产品”];
//先按上次更改的照片排序
NSSortDescriptor*sortDescriptor=[[NSSortDescriptor alloc]initWithKey:@“photoModificationDate”升序:否];
[ProductFetchRequestSetSortDescriptors:@[sortDescriptor];
NSPredicate*谓词=[NSPredicate PREDITEWITHFORMAT:predicateString];
[ProductFetchRequestSetPredicate:谓词];
//首先得到总数
NSUInteger numberOfProducts=[self.backgroundMOC countForFetchRequest:productFetchRequest错误:&错误];
NSLog(@“获取%d个产品的图像”,numberOfProducts);
//然后设置batchsize以获取数据块
整数批大小=25;
[productFetchRequest setFetchBatchSize:batchSize];
[productFetchRequest setFetchLimit:batchSize];
//分批取货
对于(整数偏移量=0;偏移量
}

日志显示,对于计数的前一半(numberOfProducts),它按预期工作。因此,25个产品的块被处理。在前半部分之后,循环中的fetchrequest将有0条记录。 如果我再次重试相同的代码,则只处理了一半(剩余)记录,因此总共处理了3/4。 我做错了什么?
请注意,managedObjectContext不仅被保存,而且在保存后被重置以保存内存。如果我不分块执行此操作,程序在下载大约3000张图片后会持续崩溃。

第一点:可能对
fetchLimit
fetchBatchSize
的操作有一些基本的误解

fetchLimit
fetchOffset
确定提取哪些记录以及提取多少记录

fetchBatchSize
指示在一次访问持久存储期间应检索多少条记录。因此,如果(有或没有
fetchBatchSize
)将要检索的记录数为100,则
fetchBatchSize
为25将导致4次到存储的行程。(换句话说,对于典型的SQLite存储,执行了4条SQL语句。然而,这一切都发生在幕后。)

因此,代码片段

request.fetchLimit      = x; 
request.fetchBatchSize  = x;
这是多余的。无论如何,去商店的次数总是一次

第二点:我不确定你对第二个主运行中心的设置是否有意义。我想你已经在后台线程中了。据我所知,重置主运行中心相当昂贵。如果禁用MOC的撤消管理器,则实际上没有必要。至于循环,我相信您可以获取所有记录,让
fetchBatchSize
处理离散的“分块”。由于核心数据的错误行为,循环中的
@autoreleasepool
可能只带来有限的优势

下载图像时,
@autoreleaspool
很有用。也许这一部分的批处理就足够了

也就是说,你可能不想改变(某种程度上)有效的东西

第三点:根据未知(对我们来说)谓词字符串计算记录数。它是动态的吗?不确定这是否也是问题的一部分。毕竟,由于不知道它是什么,记录数量的变化令人惊讶


最后:检查您是否可以不重置主运行中心

第一点:关于
fetchLimit
fetchBatchSize
的作用,可能存在一些基本的误解

fetchLimit
fetchOffset
确定提取哪些记录以及提取多少记录

fetchBatchSize
指示在一次访问持久存储期间应检索多少条记录。因此,如果(有或没有
fetchBatchSize
)将要检索的记录数为100,则
fetchBatchSize
为25将导致4次到存储的行程。(换句话说,对于典型的SQLite存储,执行了4条SQL语句。然而,这一切都发生在幕后。)

因此,代码片段

request.fetchLimit      = x; 
request.fetchBatchSize  = x;
这是多余的。无论如何,去商店的次数总是一次

第二点:我不确定你对第二个主运行中心的设置是否有意义。我想你已经在后台线程中了。据我所知,重置主运行中心相当昂贵。如果禁用MOC的撤消管理器,则实际上没有必要。至于循环,我相信您可以获取所有记录,让
fetchBatchSize
处理离散的“分块”。由于核心数据的错误行为,循环中的
@autoreleasepool
可能只带来有限的优势

下载图像时,
@autoreleaspool
很有用。也许这一部分的批处理就足够了

也就是说,你可能不想改变(某种程度上)有效的东西

第三点:根据未知(对我们来说)谓词字符串计算记录数。它是动态的吗?不确定这是否也是问题的一部分。毕竟,不知道
for (NSInteger offset = MAX(numberOfProducts - batchSize, 0); offset > 0; offset -= batchSize)