Improving Performance and Stability of Core Data

Fetch only what is required.

Your UI can not show all the data that exists in the table anyway. Don’t put extra pressure on core data to fetch data what you are not displaying on the screen. Every app has a different requirement for performance. You need to test the performance of your app by experimenting with batchSizes and fetching objects as faults.

If you are not going to update or read managedObject relations, try using NSDictionaryResultType for fetchRequest result type. Specify which properties needs to be fetched.

Use attribute types smartly, don’t use string for all. Numerical operations are always way faster than string operations.

In case of Predicates, always specify numerical predicates before string related predicates. String comparisons eat up way too many clock cycles, numeric comparisons are very fast.

In case of string predicates Beginswith, Endwith are fastest and Contains, Matches are costliest operations. Matches use regular expressions to perform operations.

More about string search in coming post…

Data duplication isn’t bad in case of relationships. It makes fetching faster.

While creating to-many relationships, make relation Cascade and Nullify.

In case of Department(to-many)Employee relation, employee to department relation should be Nullify and department to employee relation should be Cascade depending on requirements. What Cascade does is automatically deletes associated employee objects when department object is deleted, Nullify doesn’t delete objects - It breaks the relation between objects and sets relation to nil.

Turn ON indexing only for attributes used in searching, fetching.

Indexing increases insert and update time, larger the number of insertions or updates, more is the time taken for creating indexes.

Make use of multiple ManagedObjectContexts using parent and child relation. (iOS5 onwards)

Parent ManagedObjectContext should be of Concurrency Type NSMainQueueConcurrencyType. This is supposed to be only used for MainThread UI activities. Chile ManagedObjectContext should be made NSPrivateQueueConcurrencyType. Make larger inserts and updates on this context in background and save child context followed by parent context save. Chile context save merges changes into master/parent context and final parent context save actually writes data to sqlite file.

Best way to delete all data is to break the complete Core Data Stack.

To delete all the data, delete the sqlite file. Its much faster than traversing and deleting each object and its relationship.

Use multiple ObjectModels and Sqlite files when required, Its not mandatory to use only one.

If you need to delete partial data (Upon logout or some similar action), its a good idea to physically separate data which needs to be deleted. Just delete the sqlite file when you need to.

Put Core Data Stack code anywhere but not in App Delegate, keep it as a separate object itself if possible eg. VCCoreDataStack.

See what is happening under the hood.

Pass following arguments on launch of the app,

-com.apple.CoreData.SQLDebug 1

Pass argument 1, 2 or 3. Depending on what all data you need to see.