提问人:Joshua 提问时间:8/16/2010 更新时间:9/21/2013 访问量:7195
如何提高核心数据性能?
How to improve Core Data performance?
问:
我的应用程序有一个 UISearchBar,允许用户输入搜索关键字。每次击键都会执行一个核心数据查询,以便将结果显示为搜索栏更改中的文本。
问题是搜索栏击键滞后得很厉害......肯定是因为获取速度慢。任何如何提高性能的想法?
我的核心数据由包含 1000 个对象的 sqlite 数据存储提供支持。
// searchKeyword is the string appears in UISearchBar
// Both title and author may contain several words so I can't use BEGINSWITH
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(author CONTAINS[c] %@) OR (title CONTAINS[c] %@)", searchKeyword, searchKeyword];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:managedObjectContext];
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
[request setFetchLimit:10];
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
execute request and fetch the results
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
NSError* error = nil;
BOOL success = [fetchedResultsController performFetch:&error];
[request release];
答:
您可以以增量方式创建 trie,以便为过去的查询提供索引(结果集由叶节点指向)。但这不会提高单个查询的性能。您还可以调整击键系统,不要在每次击键后进行提取,而仅在击键后进行提取,之后在识别另一个击键之前经过的时间间隔(作为阈值)
虽然它不会加快查询速度,但将查找放入后台线程将阻止击键滞后。
评论
启动应用程序时,请建立完整的尝试,并在编辑时进行调整。不要使用那个愚蠢的谓词。您只获取 1000 条记录,因此应该不需要时间。
评论
使用 CONTAINS 会减慢速度。您需要做的是创建一个名为 searchWords(或其他)的新表,并在该表中存储标题中的所有单词,将其设置为小写并删除重音符号。它们具有将它们与原始对象链接的关系。确保单词字段已编入索引。
对此表执行查询,但不要使用 CONTAINS 或 BEGINSWITH,而是执行类似操作
词>“术语”和词<“燕鸥”
请注意,其中的第一个字符串是搜索词,第二个字符串是最后一个字符递增的搜索词。这允许 Core Data 使用 SQL 索引来执行搜索。
Apple 有一个 Core Data WWDC 会议来解释这一点,包括示例代码。示例代码包含一个类,该类处理字符串的规范化(即删除大小写),并以 unicode 感知方式递增单词的最后一个字符。
评论
虽然 Amoyra 的建议是合理的,但您也有一个设计问题。
只有在搜索字段中键入的第一个字母才能命中磁盘。在第一个字母之后,您应该只细化内存中已有内容的搜索结果。
您应该使用已有的谓词过滤内存中的数组(从第一个字母搜索开始),并避免执行 fetch 请求,因为它是不必要的。
此外,如果您要搜索内存中已有的数据(例如生活在 中),则整个搜索应该只命中内存中的对象。去磁盘是不必要的,而且非常浪费。NSFetchedResultsController
评论
fetchedObjects
-fetchedObjects
NSFetchedResultsController
NSFetchedResultsController
NSFetchedResultsController
评论