如何改进NSFetchedResultsController performFetch:性能?

时间:2022-09-27 03:18:27

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:

我在数据库中只有3237条记录,我使用UISearchDisplayController和NSFetchedResultsController进行搜索。但是当我为搜索键入关键字时,它非常慢:

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代码:

- (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.

有什么问题吗?我怎样才能提高性能?最好的祝福。

1 个解决方案

#1


7  

Using a CONTAINS predicate is slow, particularly if it's case insensitive. Using two makes it even slower.

使用CONTAINS谓词很慢,特别是如果它不区分大小写。使用两个使它更慢。

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:

Apple通过不实际进行全文搜索,使其应用​​程序中的“全文”搜索看起来很快。他们的大多数应用程序使用前缀搜索,依赖于如果您正在搜索“Frank”的概念,那么您不会输入“ran”。此外,它们会对属性进行规范化,并进行基于订购的搜索:例如:如果你有一个firstName属性,其内容类似“François”,你创建一个派生的normalizedFirstName属性,丢失case和变音符号(“francois”)。然后你搜索“franc”获得谓词:

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.

有关详细信息,请参阅DerivedProperty示例代码和/或WWDC 2010会话137的视频(均在developer.apple.com上)。

#1


7  

Using a CONTAINS predicate is slow, particularly if it's case insensitive. Using two makes it even slower.

使用CONTAINS谓词很慢,特别是如果它不区分大小写。使用两个使它更慢。

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:

Apple通过不实际进行全文搜索,使其应用​​程序中的“全文”搜索看起来很快。他们的大多数应用程序使用前缀搜索,依赖于如果您正在搜索“Frank”的概念,那么您不会输入“ran”。此外,它们会对属性进行规范化,并进行基于订购的搜索:例如:如果你有一个firstName属性,其内容类似“François”,你创建一个派生的normalizedFirstName属性,丢失case和变音符号(“francois”)。然后你搜索“franc”获得谓词:

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.

有关详细信息,请参阅DerivedProperty示例代码和/或WWDC 2010会话137的视频(均在developer.apple.com上)。