CoreData is slow because there are a lot of objects. How can I optimize it?

I have an entity1 that contains an NSOrderedSet of entity2. Entity2 has 100 string fields.

I create a managedObject of entity2 per second for 2-3 hours and add it to entity1. I can create some entity1 per day. I do it every day! I canโ€™t create them rarely (required).

So, in one week, my CoreDate database will contain (7 * 3 or 4) 21 or 28 managed objects of object 1, which contains (21 * 2 or 3 * 3600) 226800 objects of object2.

And each subsequent operation (insert, delete, save) using coreData will go slower than before.

How can I solve this problem?

0
source share
2 answers

So, your application will forever delay more and more user storage? Sounds like a good way to remove.

If you are dealing with a lot of data and want to get fast query results so that your application is responsive, you should use concurrency with Core Data so that the actual work with the data is performed in a different thread, and as soon as everything is loaded, your user can update interface. The modern way to do this is by combining the creation of MOC with the concurrency type and using parent / child contexts or using the new asynchronous fetch introduced in iOS 8.

+2
source

In addition to other respondents, I provide the following recommendations ...

Create two contexts while building your main data stack and use:

  • NSPrivateQueueConcurrencyType,
  • NSMainQueueConcurrencyType.

Know that you need to connect the NSPersistentStoreCoordinator to the NSPrivateQueueConcurrencyType .

and [UPDATE]

Make the NSPrivateQueueConcurrencyType parent of NSMainQueueConcurrencyType .

I prepared my Core Data solutions based on what I learned by reading the book by Marcus Zarra from The Pragmatic Bookshelf - โ€œBasic Data, Second Edition, Data Warehouse and Management for iOS, OS X and iCloudโ€ (January 2013 ), in particular the chapters (4) Performance tuning and (5) Threading.

For a more up-to-date and comprehensive solution that I have not yet implemented, read this Zarra My Core Data Stack article.

My solution involves creating a custom save method created next to (in the same class) as my main data stack, as shown below. Note that the save method is called at the appropriate points in the code.

Using this mechanism, permanent and regular saves are stored in memory (fast) in the main queue, and saving in the database is stored on disk (slow) in a private queue.

Perhaps this is the right way for you to consider - does it work very well for me?

Properties ...

 @property (nonatomic, strong) NSManagedObjectContext *mocPrivate; @property (nonatomic, strong) NSManagedObjectContext *mocMain; 

Custom save method ...

 - (void)saveContextAndWait:(BOOL)wait { if ([self.mocMain hasChanges]) { [self.mocMain performBlockAndWait:^{ NSError __autoreleasing *error; BOOL success; if (!(success = [self.mocMain save:&error])) NSLog(@"%@ - %@ - CORE DATA - E~R~R~O~R saving managedObjectContext MAIN: %@, %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), error.localizedDescription, error.localizedFailureReason); NSLog(@"%@ - %@ - CORE DATA - Success saving managedObjectContext MAIN?: %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), success ? @"YES_" : @"NO_"); }]; } void (^savePrivate) (void) = ^{ NSError __autoreleasing *error; BOOL success; if (!(success = [self.mocPrivate save:&error])) NSLog(@"%@ - %@ - CORE DATA - E~R~R~O~R saving managedObjectContext PRIVATE: %@, %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), error.localizedDescription, error.localizedFailureReason); NSLog(@"%@ - %@ - CORE DATA - Success saving managedObjectContext PRIVATE?: %@", NSStringFromClass(self.class), NSStringFromSelector(_cmd), success ? @"YES_" : @"NO_"); }; if ([self.mocPrivate hasChanges]) { if (wait) { [self.mocPrivate performBlockAndWait:savePrivate]; } else { [self.mocPrivate performBlock:savePrivate]; } } } 
+1
source

Source: https://habr.com/ru/post/1244191/


All Articles