3

データベースには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; 
}

何か問題ある?どうすればパフォーマンスを向上させることができますか?よろしくお願いします。

4

1 に答える 1

7

述語の使用CONTAINSは、特に大文字と小文字を区別しない場合は遅くなります。2つ使用すると、さらに遅くなります。

Appleは、実際に全文検索を行わないことで、アプリでの「全文」検索を高速に見せています。ほとんどのアプリは代わりにプレフィックス検索を使用しており、「Frank」を検索する場合は「ran」と入力しないという概念に依存しています。また、属性を正​​規化し、代わりに順序ベースの検索を実行します。たとえば、firstName「François」のようなコンテンツを持つnormalizedFirstNameプロパティがある場合、大文字と小文字と発音区別符号(「francois」)を失う派生プロパティを作成します。次に、「franc」を検索すると、述語が取得されます。

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

この述語ははるかに高速です。

複数の単語の文字列を含むことができるプロパティがあり、文字列上の任意の単語に対して同様のプレフィックスマッチングを実行する場合は、キーワードの関連エンティティを作成し、サブクエリを使用して、キーワードが述語に適合するエンティティを照合できます。

詳細については、DerivedPropertyサンプルコードおよび/またはWWDC 2010セッション137のビデオ(両方ともdeveloper.apple.com)を参照してください。

于 2012-06-26T05:46:20.330 に答える