iOS CoreData batch insert?

21,157

Solution 1

Check out the Efficiently Importing Data chapter from the Core Data Programming Guide.

I'm currently having the same problems as you, only I'm inserting 10000 objects and it takes around 30s, which is still slow for me. I'm doing a [managedObjectContext save] on every 1000 managed objects inserted into the context (in other words, my batch size is 1000). I've experimented with 30 different batch sizes (from 1 to 10000), and 1000 seems to be the optimum value in my case.

Solution 2

I was looking for the answer to a similar question when I came across this one. @VladimirMitrovic's answer was helpful at the time for knowing that I shouldn't save the context every time, but I was also looking for some sample code.

Now that I have it, I will provide the code below so that other people can see what it might look like to do a batch insert.

// set up a managed object context just for the insert. This is in addition to the managed object context you may have in your App Delegate.
let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator // or wherever your coordinator is

managedObjectContext.performBlock { // runs asynchronously

    while(true) { // loop through each batch of inserts. Your implementation may vary.

        autoreleasepool { // auto release objects after the batch save

            let array: Array<MyManagedObject>? = getNextBatchOfObjects() // The MyManagedObject class is your entity class, probably named the same as MyEntity
            if array == nil { break } // there are no more objects to insert so stop looping through the batches

            // insert new entity object
            for item in array! {
                let newEntityObject = NSEntityDescription.insertNewObjectForEntityForName("MyEntity", inManagedObjectContext: managedObjectContext) as! MyManagedObject
                newObject.attribute1 = item.whatever
                newObject.attribute2 = item.whoever
                newObject.attribute3 = item.whenever
            }
        }

        // only save once per batch insert
        do {
            try managedObjectContext.save()
        } catch {
            print(error)
        }

        managedObjectContext.reset()
    }
}
Share:
21,157

Related videos on Youtube

james
Author by

james

Updated on July 09, 2022

Comments

  • james
    james almost 2 years

    In my iPhone application, i need to insert ~2000 records into Core Data before the user can use any features of the application. I am loading the records into CoreData from a local JSON file. This process is taking a long time(2.5+ minutes), but only needs to happen once(or every ~10 application opens to get updated data).

    Is there a batch insert for Core Data? How can i speed up this insert process?

    If i can't speed it up using Core Data, what are the other recommended options?

  • james
    james over 13 years
    ahh, i'm doing a save for each item. i was unaware that i don't have to save after each one. moving the save call outside my loop made it much quicker! down to ~5 seconds
  • Alex Stone
    Alex Stone over 12 years
    This might have potential power saving implications as well. I noticed that after starting to use core data and inserting ~30000 objects one after another, at a rate of 1 insertion/second my app started to consume ~20% more battery life over 9 hours!
  • Suragch
    Suragch about 7 years
    @AbhishekThapliyal, I haven't learned Obj-C so I won't be able to. However, I you figure out how to do it, I suggest you add your own answer to this question.
  • Suragch
    Suragch about 7 years
    @AbhishekThapliyal, Since I am not able to verify the Objective-C code, can you add it as a separate answer? I would be glad to upvote it.