代码之家  ›  专栏  ›  技术社区  ›  Joshua

如何提高核心数据性能?

  •  14
  • Joshua  · 技术社区  · 16 年前

    我的应用程序有一个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];
    
    5 回复  |  直到 13 年前
        1
  •  18
  •   David Snabel-Caunt    13 年前

    使用包含会减慢速度。您需要做的是创建一个名为searchwords(或其他)的新表,并在该表中存储标题中的所有单词,使用小写字母并删除重音。它们之间有一种关系,将它们链接回原始对象。确保字字段已编入索引。

    在此表上执行查询,但不要使用contains或beginsWith,而是执行如下操作

    word>“term”和word<“tern”

    注意,这里的第一个字符串是搜索项,第二个字符串是最后一个字符递增的搜索项。这允许核心数据使用SQL索引执行搜索。

    苹果有 Core Data 解释此问题的WWDC会话,包括示例代码。示例代码包含一个类,该类处理字符串的规范化(即删除大小写),并以Unicode感知的方式递增单词的最后一个字符。

        2
  •  13
  •   Marcus S. Zarra    16 年前

    虽然Amoyra的建议是合理的,但您也有一个设计问题。

    只有在搜索字段中键入的第一个字母 曾经 击中磁盘。在第一个字母之后,您应该只精炼已经存在于内存中的搜索结果。

    您应该使用已有的谓词过滤内存中的数组(从第一个字母搜索中),并避免执行提取请求,因为这是不必要的。

    此外,如果要搜索已经存在于内存中的数据(例如,生活在 NSFetchedResultsController )然后,整个搜索应该只命中内存中的对象。去磁盘是不必要的,而且是非常浪费的。

        3
  •  4
  •   cobbal    16 年前

    虽然它不会加快查询速度,但将查找放入后台线程将阻止击键滞后。

        4
  •  2
  •   rano    16 年前

    您可以创建一个 trie 递增,以便为过去的查询建立索引(结果集由叶节点指向)。但它不会提高单个查询的性能。您还可以调整击键系统,不要在每次击键后执行提取,而是只在击键之后,在识别另一次击键之前经过一个时间间隔(作为阈值)。

        5
  •  -1
  •   Stephan Eggermont    16 年前

    启动应用程序时,构建完整的trie,并在编辑时对其进行调整。不要使用那个愚蠢的谓词。你只获取了1000条记录,所以这应该不会花时间。