I have some serious performance issues when querying a sqlite database with approx. 25k rows.
What I want to do is the following: as the user types something into a textfield I want to give him autocompletition suggestions in a tableview which is the inputAccessoryView of the keyboard. Each time he enters a new character, 4 new queries go off to search for appropriate suggestions. I do this in a seperate thread using GCD and blocks.
However the performance is too low. Here’s the code for one query:
- (void) queryDatabase:(NSString *) searchString
{
[self.fetchedResults removeAllObjects];
dispatch_queue_t fetchQueue = dispatch_queue_create("Fetch Queue", NULL);
dispatch_async(fetchQueue,^{
NSError *error = nil;
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.undoManager = nil;
[context setPersistentStoreCoordinator: self.persistentStoreCoordinator];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"reducedTownName like %@", [searchString stringByAppendingString:@"*"]];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Station" inManagedObjectContext:context];
request.fetchLimit = 20;
[request setIncludesPropertyValues:NO];
request.predicate = predicate;
request.resultType = NSManagedObjectIDResultType;
NSArray *results = [context executeFetchRequest:request error:&error];
NSEnumerator *e = [results objectEnumerator];
NSManagedObjectID *objectId = nil;
while (objectId = [e nextObject])
{
Station *station = (Station *) [self.managedObjectContext objectWithID:objectId];
if ( ![self.fetchedResults containsObject:station])
[self.fetchedResults addObject:station];
}
dispatch_async(dispatch_get_main_queue(),^{
[self.tableView reloadData];
});
[request release];
[context release];
});
//do 3 more queries similar to the first (only predicate changes)
dispatch_release(fetchQueue);
}
I use an NSArray (fetchedResults) to hold the returned Entities and update the tableView with data from this Array.
Does someone see any performance killer in this code, or has some other advice for me?
Ok I finally got it. Replaced the LIKE query with
where the first argument is the search term and the second argument is again the search term, except the last letter is replaced by the following one, eg.
This is extremely fast and gives me the results I wanted. I also could move the queries in the main thread, which gave me an extra boost in performance.
Greetings
Sam