如何在 CoreData 中正确添加大型数据集?

Posted

技术标签:

【中文标题】如何在 CoreData 中正确添加大型数据集?【英文标题】:How to correctly add large dataset in CoreData? 【发布时间】:2013-04-03 06:55:10 【问题描述】:

我有一个巨大的 NSArray(4.000.000 个对象),我想将其保存到 Core Data 中。 因为我使用 ARC 并且自动释放池可能会变得太大,所以我将进程划分为多个循环(这样自动释放池就有机会耗尽自身)。

在以下代码中,我使用管理器 (clMan) 从数组(区域)内的字典中添加项目。字典包含两个字符串字段,它们被解析为标量整数。

将数据划分为多个循环的代码

int loopSize = 50000;
int loops = 0;
int totalRepetitions = regions.count;
loops = totalRepetitions / loopSize;
int remaining = totalRepetitions % loopSize;


loops += 1;


for (int i = 0; i < loops; i++) 

    int k = 0;
    if (i == 0) k = 1;

    if (i == (loops - 1))
    
            // Last loop

            for (long j = i * loopSize + k; j < i * loopSize + remaining; j++) 
                [clMan addItemWithData:[regions objectAtIndex:j]];
            
            [clMan saveContext];
            break;

    

    // Complete loops before the last one
        for (long j = i * loopSize + k; j < (i + 1) * loopSize; j++) 
            [clMan addItemWithData:[regions objectAtIndex:j]];
        
        [clMan saveContext];
        NSLog(@"Records added : %d", i * loopSize);


NSLog(@"Finished adding into core data");

将数据添加到核心数据中的代码:

-(void)addItemWithData:(NSDictionary *)data


    MyRegion *region = [NSEntityDescription
                                              insertNewObjectForEntityForName:@"MyRegion"
                                              inManagedObjectContext:self.context];


    region.index = [((NSString *)[data objectForKey:REGION_INDEX]) intValue];
    region.id = [((NSString *)[data objectForKey:REGION_ID]) intValue];

 

程序在达到 1 500 000 索引时崩溃。由于解析问题/逻辑,崩溃似乎没有发生。

谁能告诉我我的逻辑是否错误,或者在 CoreData 中添加这么多数据的正确方法是什么?

【问题讨论】:

你有没有想过为此使用Magical Record?它具有非常好的自动从数组和字典导入数据的设置。 除非你将它们包装在@autoreleasepool 中,否则你的循环将无济于事。正如迈克尔·罗斯在他的回答中所建议的那样,您还需要 reset MOC。 【参考方案1】:

在每个循环之后,尝试调用NSManagedObjectContext.reset 以“忘记” MOC 中的本地副本。否则这些可能不会被清除并导致问题。

iCloud 上的 WWDC 2012 代码示例有一个名为 seedStore 的方法,它们将本地核心数据 SQL 数据库迁移到 iCloud 数据库 - 使用 5000 条记录的批量大小,并明确指出:

if (0 == (i % batchSize)) 
    success = [moc save:&localError];
    if (success) 
        /*
           Reset the managed object context to free the memory for the inserted objects
           The faulting array used for the fetch request will automatically free
           objects with each batch, but inserted objects remain in the managed
           object context for the lifecycle of the context
         */
        [moc reset];
     else 
        NSLog(@"Error saving during seed: %@", localError);
        break;
    

(这里i是批次的当前索引,因此i % batchSize == 0如果我们开始一个新批次)

【讨论】:

以上是关于如何在 CoreData 中正确添加大型数据集?的主要内容,如果未能解决你的问题,请参考以下文章

Spacy,在 python 中的大型数据集上使用 nlp.pipe,多处理导致进程进入睡眠状态。如何正确使用所有 CPU 内核?

基础入门:如何用自然语言分析大型数据集?

带有大型数据集的 SQL 插入

如何处理大型但不是大数据的数据集?

大型数据集上的核心数据获取请求缓慢

在大型数据集上训练异常检测模型并选择正确的模型 [关闭]