如何提高 NSFetchedResultsController performFetch: 性能?

Posted

技术标签:

【中文标题】如何提高 NSFetchedResultsController performFetch: 性能?【英文标题】:How to improve NSFetchedResultsController performFetch: performance? 【发布时间】:2012-06-26 02:43:10 【问题描述】:

我在数据库中只有 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.

我的 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;

以及搜索代码:

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

有什么问题吗?以及如何提高性能? 最好的问候。

【问题讨论】:

【参考方案1】:

使用CONTAINS 谓词很慢,尤其是在不区分大小写的情况下。使用两个会使它变得更慢。

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

normalizedFirstName >= "franc" AND normalizedFirstName < "frand"

这个谓词要快得多。

如果您有一个可以包含多字串的属性,并且您想对字符串上的任何字进行类似的前缀匹配,您可以为关键字创建相关实体,并使用子查询来匹配关键字与谓词匹配的实体.

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

【讨论】:

以上是关于如何提高 NSFetchedResultsController performFetch: 性能?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能两次获取相同的数据? NSFetchedResultsController 为空

启动 Core Data 应用程序时在后台配置 NSFetchedResultsController

如何有效的提高我团队的工作效率?

多表联查如何提高效率

如何提高UBOOT的启动速度

目前大一,在学C++,编程能力如何快速提高?