3

我在數據庫中只有3237條記錄,我使用UISearchDisplayController和NSFetchedResultsController進行搜索。但是當我搜索輸入關鍵字這是非常緩慢:如何提高NSFetchedResultsController performFetch:性能?

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

有什麼問題嗎?我怎麼能提高性能? 此致敬禮。

回答

7

使用CONTAINS謂詞很慢,尤其是在不區分大小寫的情況下。使用兩個使其更慢。

蘋果通過不實際進行全文搜索而在其應用中實現「全文」搜索。他們的大多數應用程序都使用前綴搜索,而依賴於這樣的概念:如果您搜索「Frank」,則不會輸入「ran」。此外,他們規範化屬性並進行基於排序的搜索:例如如果您的firstName屬性的內容類似於「François」,則會創建派生的normalizedFirstName屬性,該屬性會丟失大小寫和變音符號(「francois」)。然後你的搜索「法郎」得到的謂詞:

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

這個謂詞是一個快很多。

如果您有一個屬性可以包含多字詞字符串,並且您希望對字符串上的任何單詞執行類似的前綴匹配,則可以爲關鍵字創建相關實體並使用子查詢來匹配其關鍵字符合謂詞。

有關詳細信息,請參閱DerivedProperty示例代碼和/或WWDC 2010會話137的視頻(均位於developer.apple.com上)。