Reputation: 303
I have only 3237 records in the database and I used UISearchDisplayController and NSFetchedResultsController for search. but when I type the keyword for search it's extremely slow:
2012-06-26 10:26:25.264 KYBD[3863:707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZARTICLEPARTCHINESE, t0.ZARTICLEPARTENGLISH, t0.ZARTICLEPARTNUMBER, t0.ZARTICLE FROM ZARTICLECONTENT t0 LEFT OUTER JOIN ZARTICLES t1 ON t0.ZARTICLE = t1.Z_PK WHERE ( NSCoreDataStringSearch( t0.ZARTICLEPARTENGLISH, ?, 257, 0) OR NSCoreDataStringSearch( t0.ZARTICLEPARTCHINESE, ?, 257, 0)) ORDER BY t1.ZARTICLETITLE, t0.ZARTICLEPARTNUMBER
2012-06-26 10:26:26.438 KYBD[3863:707] CoreData: annotation: sql connection fetch time: 0.5325s
2012-06-26 10:26:26.446 KYBD[3863:707] CoreData: annotation: total fetch execution time: 1.1821s for 2549 rows.
2012-06-26 10:26:26.489 KYBD[3863:707] CoreData: sql: SELECT t1.ZARTICLETITLE, COUNT (DISTINCT t0.Z_PK) FROM ZARTICLECONTENT t0 LEFT OUTER JOIN ZARTICLES t1 ON t0.ZARTICLE = t1.Z_PK WHERE ( NSCoreDataStringSearch( t0.ZARTICLEPARTENGLISH, ?, 257, 0) OR NSCoreDataStringSearch( t0.ZARTICLEPARTCHINESE, ?, 257, 0)) GROUP BY t1.ZARTICLETITLE ORDER BY t1.ZARTICLETITLE
2012-06-26 10:26:26.874 KYBD[3863:707] CoreData: annotation: sql connection fetch time: 0.3733s
2012-06-26 10:26:26.879 KYBD[3863:707] CoreData: annotation: total fetch execution time: 0.3904s for 100 rows.
My NSFetchedResultsController code:
- (NSFetchedResultsController *)fetchedResultsController {
if (!_fetchedResultsController) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"ArticleContent" inManagedObjectContext:self.managedObjectContext];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"article.articleTitle" ascending:YES];
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:@"articlePartNumber" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sort, sort2, nil];
request.predicate = nil;
[NSFetchedResultsController deleteCacheWithName:@"searchResults"];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"article.articleTitle" cacheName:@"searchResults"];
}
return _fetchedResultsController;
}
and the code for search:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
if ([searchString length] > 0) {
[NSObject cancelPreviousPerformRequestsWithTarget:self.fetchedResultsController selector:@selector(performFetch:) object:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"articlePartEnglish CONTAINS[c] %@ OR articlePartChinese CONTAINS[c] %@", searchString, searchString];
self.fetchedResultsController.fetchRequest.predicate = predicate;
[NSFetchedResultsController deleteCacheWithName:@"searchResults"];
[self.fetchedResultsController performFetch:nil];
}
return YES;
}
Is there any problem? and how could I improve the performance? Best regards.
Upvotes: 3
Views: 1838
Reputation: 126177
Using a CONTAINS
predicate is slow, particularly if it's case insensitive. Using two makes it even slower.
Apple makes "full-text" search in its apps look fast by not actually doing full-text search. Most of their apps use prefix search instead, relying on the notion that if you're searching for "Frank", you're not going to type "ran". Also, they normalize attributes and do ordering-based searches instead: e.g. if you have a firstName
property with content like "François", you create a derived normalizedFirstName
property that loses the case and diacritics ("francois"). Then your search for "franc" gets the predicate:
normalizedFirstName >= "franc" AND normalizedFirstName < "frand"
This predicate is a whole lot faster.
If you have a property that can contain multi-word string and you want to do similar prefix matching on any word on the string, you can create a related entity for keywords and use a subquery to match entities whose keywords fit the predicate.
See the DerivedProperty sample code and/or the video of WWDC 2010 session 137 (both on developer.apple.com) for details.
Upvotes: 7