简体   繁体   中英

Slow inserts for CoreData many-to-many relationship

I have two models, with a many-to-many relationship between them. The model A starts in an empty state, while the model B has about 220k records (with a quite big index, but this shouldn't affect, since this model is never updated).

The to-many from A->B is as follows:

  • optional => false
  • transient => false
  • indexed => true
  • ordered => true
  • minCount => 0
  • maxCount => NSIntegerMax
  • deleteRule => NSCascadeDeleteRule

The to-many from B->A is as follows:

  • optional => true
  • transient => false
  • indexed => false
  • ordered => false
  • minCount => 0
  • maxCount => NSIntegerMax
  • deleteRule => NSNullifyDeleteRule

And of course, each relationship is set as inverse of the other. The problem I'm facing is the following: prior to create a new entity A, the app performs a fetch request which gets about 2k records of the entity B. Then, the app sets these records to the entity A about to be created, and then saves the context. The problem is setting the nsorderedset of 2k records to the entity A instance is taking 4 seconds more or less in an iPhone 4S with iOS 6.0.1, and saving the context is taking another 4 seconds more or less, in the same device. That makes 8 seconds to create a new instance of model A.

I've tried enabling/disabling the indexed association property in model A, but that didn't make such a difference. It's that heavy the task I'm trying to achieve?

Making some tests, I've observed that most of the time lost setting the nsorderedset to the entity A instance is because of the inverse relationship. I made a quick test changing the many-to-many relationship to a to-many without inverse relationship in the target model, and then the insert time went down to half the time. Of course this breaks the many-to-many relationship. It was just a quick test.

Am I missing something here? Since the app is saving the context just one time, and not one time per each record B, it shouldn't take that long to save 2k records, but I'm new to iPhone development, and maybe this task I'm performing is too much for this kind of device.

Any hints would be greatly appreaciated. Thanks!

Ferdev,

Thank you for a well written question. It is clear you have thought carefully about your problem before asking for help. This helps everyone.

Core Data does not appear to use block operations when it saves. Hence, you are going to have performance issues there. The relationship setting though should be faster than you're seeing.(BTW, most of the performance issues are driven by the speed of flash memory. It is slow on iOS devices. Hence, prefetching to keep your MOC hot with your data is important. Bulk fetching is important.)

I make several observations:

Why is the A->B to-many relationship both indexed and ordered? The ordering will slow down your inserts. Does it also make sense to index a relationship?

Are you using the bulk relationship setters ( -add<Key>: )?

Are you fetching all 2000 of your entity B records before you set them to the entity A instance?

Even though this doesn't affect your insert performance, why does the delete rule from A->B cascade? You write above entity B doesn't change.

Andrew

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM