Sqlite or Core Data to update more then 50000 records

I'm currently using coredata for my project. But when the api returns 54000 objects that the app need to update, the user has to wait almost 2 hours. It's the major problem for the current project and I am thinking to use sqlite and not using coredata anymore to update thousands of objects.

Is it a right decision to use Sqlite or is there any suggestion for CoreData? I can't decide. Any help will be great. Thank you.

Here is what I am doing:

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 hours is very long. That's weird.

Yet you can massage your code by having core data do less work. Much less work.

  • Perform a single fetch request instead of 54K fetch requests
  • Don't call a managed object property setter when a property value does not change , so that no object is unnecessarily flagged as dirty, and Core Data does not have to perform a costly but useless update of the object when the "save" method is invoked.
  • This will dramatically reduce the amount of work performed by Core Data, and the performance of your application.

    The second point is easy, but very verbose: compare each individual property values with dictionary values before calling setters.

    The first point requires an algorithm change:

    Perform a single fetch request, sorted by id (with [NSFetchRequest setSortDescriptors:])

    Sort dictionaries by id (with [NSArray sortedArray...])

    Synchronize the two sorted lists (it is paramount that both lists are sorted):

    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];
    }
    

    And save.

    Finally, maybe SQLite will be faster (see https://github.com/groue/GRDB.swift/wiki/Performance for an attempt at comparing the performance of Core Data with SQLite libraries).

    But SQLite won't turn a slow algorithm into a fast one .


    Core Data provides NSBatchUpdateRequest which allows you to make updates directly on the persistent store without involving instantiating and processing managed objects in memory.

    You should run this code using the core data performance instrument as well. If itemList contains 54,000 objects then you are performing 54,000 fetches to the persistent store to check a single ID each time. It would be far faster to fetch all of the IDs up front and then check the results in memory than to perform repeated fetch requests - that code will be almost as slow in raw SQL as it is in Core Data.

    This code also looks wrong:

    ItemManagedObject *itemMO;
    
    if(itemMO.count){
    

    It's never going to pass that if test, unless you've missed a line somewhere.


    I've never redone a core data project in sqlite or visa versa. So I cannot tell you whether there is a performance difference or not/

    However the 54k = 2 hours thing sounds very strange. You talk about an API which makes me suspect a server is involved, your question is about databases. Certainly 2 hours sounds way too long and makes me wonder whether you have issues with the core design of your database. For example, lack of indexes. Depending on your queries and database, a single update could be triggering all sorts of heavy duty processing.

    Another though is why are you processing this column of data on a device. It's a lot to handle and I wonder if there are ways to reduce the volume down, selectively do updates or perhaps even better - move it to a server.

    I think you need to rethink your question. Provide more context about the database, exactly what you are doing with it and why.

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

    上一篇: 如何在openGL中绘制背景

    下一篇: Sqlite或Core Data来更新50000条记录