Using Core Data Efficiently
Forming Efficient Predicates
Optimizing Your Predicate
– No query optimizer in SQLite
– Eliminate largest groups first
– Put heaviest operations last
A) searchString CONTAINS “red” OR timestamp BETWEEN (X, Y)
B) timestamp BETWEEN (X, Y) OR searchString CONTAINS “red”
Option B is faster. The timestamp comparison is very fast. This will immediately eliminate some of the string comparisons that will need to take place. String comparison is slow.
Text queries are generally slow. Below is a list of predicate comparisons in order of increasing cost:
– Beginswith, Endswith
– Equality (==)
This will prefetch these relationships. So if you need them right away, do this so you don’t end up making multiple IO requests shortly thereafter.
Fetch Only What You Need
Consider returning dictionaries instead of managed objects (maybe you just need to perform a calculation based on the data and don’t need to update it).
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Quake"];[request setResultType:NSDictionaryResultType];[request setPropertiesToFetch:@[@"magnitude"]];
This will return an array of dictionaries that each have the key “magnitude” with the value of “magnitude”.
Use SQL to perform your calculations
Use an expression description:
NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];ed.name = @"minimum";ed.expression = [NSExpression expressionForFunction:@"min:" arguments:@[[NSExpression expressionForKeyPath:@"magnitude"]]];[request setPropertiesToFetch:@[ed]];
If you need to delete a very large number of objects, don’t perform an individual fetch for each object you need to delete. Fetch them into memory using a single fetch request and then loop through them.
Let’s say you have a list of user IDs for users that you need to delete. Use the “IN” operator to perform a single fetch that retrieves all the users at once. If you have memory concerns with fetching so many objects, you can perform the fetch/deletions in batches.
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"userID IN %@", userIDsToDelete];
It is possible to have Entities that inherit from other Entities with Core Data. However, this should be used cautiously. Below is an example of three entities (Employee, Contractor, & Boss) which all inherit from Person. Each entities attributes are listed.
A single table will be created which is used for all entities that inherit from Person. All non-relevant fields will be NULL. This is less space efficient and fetches will be slower.
Want to learn more about core data? Check out Logan’s previous post Everything Core Data.
Interested in doing this for a living?