NSSortDescriptor的性能如何?

我有一个大约4000行的SQLite支持的数据库,连接到Core Data。 该模型是一个简单的概述 – >详细模型。 每个概述(带标题和副标题)都与细节有关,其中包含详细信息。 为了查看这些数据,我实现了一个带有NSFetchedRequestController的UITableView。

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"registered_name" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObject:sort]; NSPredicate *filterPredicate = nil; NSString *sectionName = nil; NSString *cacheName = nil; NSFetchedResultsController *aFetchedResultsController = nil; aFetchedResultsController.delegate = self; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setFetchBatchSize:20]; [fetchRequest setSortDescriptors:sortDescriptors]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Info" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; [fetchRequest setPredicate:filterPredicate]; aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:sectionName cacheName:cacheName]; NSError *error = nil; if (![aFetchedResultsController performFetch:&error]) NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } [fetchRequest release]; [sort release]; return aFetchedResultsController;` 

我已经实现了所有function,但它的工作原理很慢。 具体来说,我关注的是应用程序启动。

这是在启动时减慢速度的查询(XCode中的SQL调试标志):

 CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZREGISTERED_NAME CoreData: annotation: sql connection fetch time: 0.8773s CoreData: annotation: total fetch execution time: 0.8976s for 4302 rows. 

执行performFetch后立即发生这种情况。 为什么Core Data觉得需要获取和排序我的数据库的所有4302行? 如果我将setLimit设置为较小的值,比如20,当然一切都工作得非常快,但我只显示了20个结果。 另一方面,我现在有setBatchSize,它工作得很好,我可以在调试控制台中看到SELECT语句,因为我滚动了表视图。 但它仍然在发布时排序4302行,我认为这会不必要地减慢应用程序启动时间。

我打算在NSSortDescriptor中实现一个规范化的字符串排序和一个caseInsensitiveNumericCompare选择器,根据Apple的WWDC 2010示例代码,但在我看来,我在这里缺少一些简单的东西。

更新:

似乎我不能使用自定义选择器caseInsensitiveNumericCompare:使用NSSortDescriptor,因为我使用SQLite作为数据库。 我真的不知道我还能做些什么来加快速度。 也许SQLite会通过缩短和规范化的字符串来更快地排序,这就是我接下来要尝试的。

更新2:

使用标准化字符串(除了AZ和0-9之外没有其他字母或符号),启动时间降至约0.7秒。 没有大幅减少。 我正在尝试的最后一件事是预先分配数据库,然后为行分配增量ID。 在NSSortDescriptor中,我将按此数字ID进行排序。 根据我的SQL测试,它应该大约快7倍。

我解决了自己的问题。 这只是提醒任何可能遇到类似问题的人。 我犯的错误不是为数据库端的必填字段创建索引。 我只是在XCode中点击了我的模型中的“索引”选项。 显然,如果您自己提供了.sqlite文件,则不会创建任何索引。

在一个奇怪的启动案例之后,Core Data决定为我创建数据库,我看到这些SQL语句被执行:

 2011-10-08 19:49:40.572 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZREGISTERED_NAME_INDEX ON ZINFO (ZREGISTERED_NAME) 2011-10-08 19:49:40.586 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZFIRSTLETTER_INDEX ON ZINFO (ZFIRSTLETTER) 2011-10-08 19:49:40.598 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZNAME_INDEX ON ZINFO (ZNAME) 2011-10-08 19:49:40.610 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZN_SL_NAME_INDEX ON ZINFO (ZN_SL_NAME) 2011-10-08 19:49:40.622 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZN_REGISTERED_NAME_INDEX ON ZINFO (ZN_REGISTERED_NAME) 2011-10-08 19:49:40.635 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZDETAILS_INDEX ON ZINFO (ZDETAILS) 

在我自己的数据库上复制这些索引后,事情已大大加快:

 CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZREGISTERED_NAME CoreData: annotation: sql connection fetch time: 0.1315s CoreData: annotation: total fetch execution time: 0.1568s for 4161 rows. 

我对这些数字非常满意。 但是因为我现在已经预先分配了我的数据库,所以我可以使用NSSortDescriptor的数字。 这让我想到:

 CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZID CoreData: annotation: sql connection fetch time: 0.0677s CoreData: annotation: total fetch execution time: 0.0890s for 4161 rows. 

所以不到9分之一秒,低于9分之一秒。