NSSortDescriptor的性能? [英] The performance of NSSortDescriptor?

查看:70
本文介绍了NSSortDescriptor的性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大约4000行的SQLite支持的数据库,已连接到Core Data。该模型是简单的概述->详细模型。每个概述(包括标题和副标题)都与一个包含详细信息的详细信息相关。为了查看此数据,我已经用NSFetchedRequestController实现了UITableView。

  NSSortDescriptor * sort = [[NSSortDescriptor alloc] initWithKey:@ registered_name升序:是]; 
NSArray * sortDescriptors = [NSArray arrayWithObject:sort];

NSPredicate * filterPredicate = nil;
NSString * sectionName = nil;
NSString * cacheName = nil;

NSFetchedResultsController * aFetchedResultsController = nil;
aFetchedResultsController.delegate =自我;
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];

[fetchRequest setFetchBatchSize:20];
[fetchRequest setSortDescriptors:sortDescriptors];

NSEntityDescription *实体= [NSEntityDescription entityForName:@ Info; inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

[fetchRequest setPredicate:filterPredicate];
aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequestmanagedObjectContext:self.managedObjectContext sectionNameKeyPath:sectionName cacheName:cacheName];

NSError *错误=无;
if(![aFetchedResultsController performFetch:& error])
NSLog(@未解决的错误%@,%@,error,[error userInfo]);
abort();
}

[fetchRequest版本];
[排序发布];
return aFetchedResultsController;`

我已经实现了所有功能,并且可以运行,但是运行缓慢。我特别关心应用程序的启动。


这是使启动时间变慢的查询(XCode中的SQL调试标志):

  CoreData:sql:SELECT 0,t0.Z_PK FROM ZINFO t0 ORDER BY t0.Zapped_NAME 
CoreData:批注:sql连接获取时间:0.8773s
CoreData:批注:总提取执行时间:4302行为0.8976s。

这是在执行performFetch之后立即发生的。为什么Core Data感到需要获取和排序数据库的所有4302行?如果将setLimit设置为较小的值(例如20),那么当然一切都会非常快,但是我只会显示20个结果。另一方面,我现在有了setBatchSize,它运行良好,并且在滚动表视图时可以在调试控制台中看到SELECT语句。但是它仍然在启动时对4302行进行排序,我认为这不必要地拖延了应用启动时间。 2010示例代码,但在我看来,这里缺少一些简单的东西。


更新:


似乎我不能使用自定义选择器caseInsensitiveNumericCompare:带有NSSortDescriptor,因为我使用SQLite作为数据库。我真的不知道我能做些什么来加快速度。也许SQLite使用缩短且规范化的字符串排序会更快,这就是我接下来要尝试的。除AZ和0-9以外的其他字母或符号),启动时间缩短至约0.7s。没有大的减少。我要尝试的最后一件事是对数据库进行预排序,然后为行分配增量ID。然后,在NSSortDescriptor中,我将按此数字ID进行排序。根据我的SQL测试,它应该快7倍左右。

解决方案

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



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

  2011-10-08 19:49:40.572 App [1717:307] CoreData:sql :在ZINFO上CREATE INDEX ZINFO_Zapped_NAME_INDEX(Zapped_NAME)
2011-10-08 19:49:40.586 App [1717:307] CoreData:sql:在ZINFO上CREATE INDEX ZINFO_ZFIRSTLETTER_INDEX(ZFIRSTLETTER)
2011-10-08 19:49:40.598 App [1717:307] CoreData:sql:在ZINFO上创建索引ZINFO_ZNAME_INDEX(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_register_NAME_INDEX ON ZINFO(ZN_register_NAME)
2011-10-08 19:49: 40.635 App [1717:307] CoreData:sql:在ZINFO上创建索引ZINFO_ZDETAILS_INDEX(ZDETAILS)

在我自己的数据库上复制了这些索引之后,事情就大大加速了:

  CoreData:sql:SELECT 0,t0。 Z_PK FROM ZINFO t0排序依据t0.Zlocated_NAME 
CoreData:注释:sql连接获取时间:0.1315s
CoreData:注释:总获取执行时间:4568行的0.1568s。

我对这些数字感到非常满意。但是,由于现在已经对数据库进行了预排序,因此可以为NSSortDescriptor使用数字。这使我想到:

  CoreData:sql:SELECT 0,t0.Z_PK FROM ZINFO t0 OR BY BY t0.ZID 
CoreData:批注:sql连接获取时间:0.0677s
CoreData:批注:总获取执行时间:4890行的0.0890s。

所以从9分之一秒降低到9分之一秒。


I have a SQLite backed database of roughly 4000 rows, connected to Core Data. The model is a simple overview -> detail model. Each overview (with title and subtitle) has a relationship to a detail, which contains detailed information. To view this data I have implemented a UITableView with a NSFetchedRequestController.

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

I have implemented everything and it works, but it works slowly. Specifically I'm concerned with the application launch.

This is the query that slows things down on launch time (SQL debug flag in XCode):

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. 

This happens immediately after performFetch is executed. Why does Core Data feel the need to get and sort all 4302 rows of my database? If I set the setLimit to a small value, say 20, of course everything works extremely fast, but I only get 20 results displayed. On the other hand, I now have setBatchSize, which works great, and I can see the SELECT statements in the debug console, as I scroll the table view. But it still sorts 4302 rows at launch, which I feel is unnecessarily slowing down app launch time.

I intend to implement a normalized string sorting and a caseInsensitiveNumericCompare selector in NSSortDescriptor, as per Apple's WWDC 2010 sample code, but it seems to me I'm missing something simple here.

Update:

Seems that I can't use a custom selector caseInsensitiveNumericCompare: with NSSortDescriptor, since I am using SQLite as the database. I really don't see what more I can do, to speed this up. Maybe SQLite will sort faster with shortened and normalized string, this is what I'm trying next.

Update 2:

With normalized string (no other letters or symbols except A-Z and 0-9), the launch time is down to about 0.7s. Not a big reduction. The last thing I'm trying is presorting the database and then assigning incremental ids to the rows. In NSSortDescriptor I will then sort by this numerical id. According to my SQL tests, it should be roughly 7x faster.

解决方案

I solved my own problem. This is just a reminder for anyone who might run into similar issues. The error I made was not creating indexes for the required fields on the database side. I just clicked the "indexed" option in my model in XCode. Apparently this DOES NOT create any indexes, if you have supplied the .sqlite file yourself.

After a curious launch case, where Core Data decided to create the database for me, I saw these SQL sentences executed:

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)

After I replicated these indexes on my own database, things have sped up considerably:

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.

I'm extremely happy with these numbers. But since I've now presorted my database, I can use a number for NSSortDescriptor. This brings me down to:

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.

So a little under 9 hundredths of a second, down from 9 tenths of a second.

这篇关于NSSortDescriptor的性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆