Sqlite或Core Data来更新50000条记录

我目前正在为我的项目使用coredata。 但是,当API返回应用程序需要更新的54000个对象时,用户必须等待近2个小时。 这是当前项目的主要问题,我正在考虑使用sqlite而不再使用coredata来更新数千个对象。

使用Sqlite是否是正确的决定还是CoreData有任何建议? 我无法决定。 任何帮助都会很棒。 谢谢。

这是我正在做的事情:

NSManagedObjectContext *privateObjectContext = [AppDelegate appDelegate].privateManagedObjectContext;
    [privateObjectContext performBlock:^{

      int i = 1;
      for (NSDictionary *item in itemlist) {
            i++;

            [fetchRequest setPredicate:[NSPredicate predicateWithFormat:
                                        @"itemID == %@",[item objectForKey:@"item_id"]
                                        ]];
            NSError *error;
            NSMutableArray *inventories = [[NSMutableArray alloc]initWithArray:
                                           [privateObjectContext executeFetchRequest:fetchRequest
                                                                               error:&error]];
            ItemManagedObject *itemMO;

            if(inventories.count){
                itemMO = inventories.firstObject;
            }else{
                itemMO = [NSEntityDescription insertNewObjectForEntityForName:@"ItemObject"
                                                       inManagedObjectContext:privateObjectContext];
            }
            [itemMO prepareWithDictionary:item];
        }

        NSError *error;
        if (![privateObjectContext save:&error]) {
            completionHandler(NO);
        }
}

2小时很长。 这很奇怪。

然而,你可以通过让核心数据做更少的工作来按摩你的代码。 更少的工作。

  • 执行单个提取请求而不是54K提取请求
  • 当属性值没有改变时不要调用管理对象属性设置器 ,以便不会将对象标记为不必要的脏数据,并且当“save”方法为“是”时,Core Data不必执行代价高昂但无用的更新调用。
  • 这将显着减少Core Data所执行的工作量以及应用程序的性能。

    第二点很简单,但非常详细:在调用setter之前,比较每个单独的属性值与字典值。

    第一点需要改变算法:

    执行单个提取请求,按id排序(使用[NSFetchRequest setSortDescriptors:])

    按id排序字典(使用[NSArray sortedArray ...])

    同步两个排序列表(两个列表排序都是最重要的):

    NSEnumerator *itemMOEnum = [itemMOs objectEnumerator];
    NSEnumerator *dicEnum = [dictionaries objectEnumerator];
    ItemManagedObject *itemMO = [itemMOEnum nextObject];
    NSDictionary *itemDic = [dicEnum nextObject];
    
    while (itemDic) {
        NSComparisonResult comparison = itemMO ? [itemDic[@"item_id"] compare:itemMO.itemID] : NSOrderedAscending;
        switch (comparison) {
            case NSOrderedSame:
                // id present in both lists: update
                [itemMO prepareWithDictionary:itemDic];
    
                itemMO = [itemMOEnum nextObject];
                itemDic = [dicEnum nextObject];
                break;
    
            case NSOrderedAscending: {
                // id present only in dictionaries: create
                itemMO = [NSEntityDescription insertNewObjectForEntityForName:@"ItemObject"
                                              inManagedObjectContext:privateObjectContext];
                [itemMO prepareWithDictionary:itemDic];
    
                itemDic = [dicEnum nextObject];
            } break;
    
            case NSOrderedDescending:
                // id present only in managed object: delete or do nothing
                itemMO = [itemMOEnum nextObject];
                break;
        }
    }
    
    while (itemMO) {
        // id present only in managed object: delete or do nothing
        itemMO = [itemMOEnum nextObject];
    }
    

    并保存。

    最后,也许SQLite会更快(请参阅https://github.com/groue/GRDB.swift/wiki/Performance,以便比较Core Data与SQLite库的性能)。

    但SQLite不会将慢速算法变成快速算法


    核心数据提供NSBatchUpdateRequest ,它允许您直接在持久性存储上进行更新,而不涉及在内存中实例化和处理管理对象。

    您应该使用核心数据性能工具来运行此代码。 如果itemList包含54,000个对象,那么您将对持久性存储执行54,000次提取,以每次检查一个ID。 要提前获取所有ID,然后检查内存中的结果比执行重复提取请求要快得多 - 原始SQL中的代码几乎与核心数据中的代码一样慢。

    此代码也看起来不正确:

    ItemManagedObject *itemMO;
    
    if(itemMO.count){
    

    如果测试不会通过,除非你在某个地方错过了一条线。


    我从来没有在sqlite中重做过核心数据项目,反之亦然。 所以我不能告诉你是否存在性能差异/

    然而54k = 2小时的事情听起来很奇怪。 你谈论的是一个API,它让我怀疑涉及服务器,你的问题是关于数据库。 当然,2小时听起来太长了,让我怀疑你的数据库的核心设计是否有问题。 例如,缺乏索引。 根据您的查询和数据库,单个更新可能会触发各种重型处理。

    另一种是你为什么要在设备上处理这一列数据。 需要处理很多事情,我想知道是否有办法减少音量,选择性地进行更新,或者甚至更好 - 将其移动到服务器。

    我认为你需要重新考虑你的问题。 提供关于数据库的更多上下文,正是你在做什么以及为什么。

    链接地址: http://www.djcxy.com/p/78201.html

    上一篇: Sqlite or Core Data to update more then 50000 records

    下一篇: SQLite snippet function implementation does not format Text as HTML in TextView