Objective c SQL与核心数据的真实性能:需要透视图和可能的特定修复

Objective c SQL与核心数据的真实性能:需要透视图和可能的特定修复,objective-c,sql,ios,core-data,Objective C,Sql,Ios,Core Data,我有一个文字游戏应用程序,可以访问文字和线索列表,大约有10万条条目。数据库仅可访问,从未更改。我使用SQL方法构建了这个应用程序,它在iOS 6上运行得非常好,但在iOS 5上从数据库中获取新线索的时间非常慢: iOS5使用SQL从100K中获取一条记录,大约需要12分钟 秒 iOS 6使用SQL从100K中获取一条记录需要 大约700-1000毫秒 这两款手机都安装在32 GB的iPod Touch上 考虑到这种性能,我使用核心数据制作了一个版本。我的方法是通过首先计算符合查询的记录,然

我有一个文字游戏应用程序,可以访问文字和线索列表,大约有10万条条目。数据库仅可访问,从未更改。我使用SQL方法构建了这个应用程序,它在iOS 6上运行得非常好,但在iOS 5上从数据库中获取新线索的时间非常慢:

  • iOS5使用SQL从100K中获取一条记录,大约需要12分钟 秒
  • iOS 6使用SQL从100K中获取一条记录需要 大约700-1000毫秒
这两款手机都安装在32 GB的iPod Touch上

考虑到这种性能,我使用核心数据制作了一个版本。我的方法是通过首先计算符合查询的记录,然后随机选择一个来获得一个随机数据库条目。代码如下。我读到的所有内容都表明核心数据会更快:

  • iOS 5,计数记录大约需要4秒,检索其中一个 这些记录大约需要50-1500毫秒。总时间约为5秒
  • iOS 6,计数记录需要2秒多一点的时间,检索 其中一条记录大约需要300-500毫秒。总共大约3秒钟
因此,与SQL相比,iOS 5上的核心数据速度更快,但iOS 6上的核心数据速度较慢。就我而言,无论哪种方式,表演都太慢了。我知道开销来自下面给出的方法(对于核心数据版本)。因此,有两个问题:

  • 关于这个问题,有什么一般性的建议可以帮助理解它并提高性能吗
  • 具体地说,下面附加的核心数据代码是什么:我是否做了一些愚蠢的事情使它变慢了?或者我应该加些别的东西来加速?这是我第一次尝试核心数据
  • 谢谢

    - (NSArray *) randomClue {
    
    NSManagedObjectContext* context = [self managedObjectContext];
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"A"];
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"WL28"
                                   inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    
    NSPredicate *predicate = [self createSearchQuery];
    [fetchRequest setPredicate:predicate];
    
    NSError *error;
    
    NSDate *date1 = [NSDate date];
    NSString *timeString1 = [formatter stringFromDate:date1];
    
    int resCount = [context countForFetchRequest:fetchRequest
                                           error:&error];
    
    NSDate *date2 = [NSDate date];
    NSString *timeString2 = [formatter stringFromDate:date2];
    
    int t1 = [timeString1 intValue];
    int t2 = [timeString2 intValue];
    int d1 = t2-t1;    
    NSLog(@"randomClue:");
    NSLog(@"    Time to count array entries: %i", d1);
    
    int ranNum = arc4random_uniform(resCount-1);
    int ranNum2 = ranNum + 1;
    
    // Now we fetch just one answer object, not a whole database or even a piece of it!
    
    [fetchRequest setReturnsObjectsAsFaults:YES];
    [fetchRequest setPropertiesToFetch:nil];
    [fetchRequest setFetchLimit:1];
    [fetchRequest setFetchOffset:ranNum2];
    
    NSDate *date3 = [NSDate date];
    NSString *timeString3 = [formatter stringFromDate:date3];
    
    self.wl28 = [context executeFetchRequest:fetchRequest error:&error];
    
    NSDate *date4 = [NSDate date];
    NSString *timeString4 = [formatter stringFromDate:date4];
    
    int t3 = [timeString3 intValue];
    int t4 = [timeString4 intValue];
    int d2 = t4-t3;
    NSLog(@"    Time to retrieve one entry: %i", d2);
    
    return self.wl28;
    }
    
    编辑:下面添加createSearchQuery

    - (NSPredicate *)createSearchQuery {
    
    NSMutableArray *pD = [[GameData gameData].curData valueForKey:@"persData"];
    NSNumber *currMin = [pD objectAtIndex:0];
    NSNumber *currMax = [pD objectAtIndex:1];
    NSNumber *dicNo = [pD objectAtIndex:2];
    NSString *dict = nil;
    
    if ([dicNo intValue] == 0) dict = @"TWL";
    if ([dicNo intValue] == 1) dict = @"LWL";
    
    NSPredicate *dictPred = [NSPredicate predicateWithFormat:@"dict == %@", dict];
    NSPredicate *lowNoCPred = [NSPredicate predicateWithFormat:@"noC >= %@", currMin];
    NSPredicate *highNoCPred = [NSPredicate predicateWithFormat:@"noC <= %@", currMax];
    
    NSPredicate *query = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray
                          arrayWithObjects:dictPred, lowNoCPred, highNoCPred,nil]];
    NSLog(@"%@", query);
    return query;
    }
    
    -(NSPredicate*)createSearchQuery{
    NSMUTABLEARRY*pD=[[GameData GameData].curData valueForKey:@“persData”];
    NSNumber*currMin=[pD objectAtIndex:0];
    NSNumber*currMax=[pD objectAtIndex:1];
    NSNumber*dicNo=[pD objectAtIndex:2];
    NSString*dict=nil;
    如果([dicNo intValue]==0)dict=@“TWL”;
    如果([dicNo intValue]==1)dict=@“LWL”;
    NSPredicate*dictPred=[NSPredicate PREDITEWITHFORMAT:@“dict==%@”,dict];
    NSPredicate*lowNoCPred=[NSPredicate谓词格式:@“noC>=%@”,currMin];
    
    NSPredicate*highNoCPred=[NSPredicate谓词格式:@"noC您可以尝试向实体中的noC和/或dict属性添加索引。这可能会加快查询时间。

    如果数据库是只读的,为什么每次都要计算条目?根据用户设置,会有子集,这反过来会影响查询。最大的子集约为70K,这就是性能数字rs是基于的。它们的数量不是无限的,所以我想我可能会预先计算它们以节省一些时间。如果您向我们展示
    createSearchQuery
    方法,这会更容易。@TomaszZabłocki感谢您的关注:我将代码添加到了原始帖子中。您能给我指一些文档吗?我已经看到提到了索引C在Xcode中打开xcdatamodel,切换到网格编辑器样式,然后选择您的实体,然后选择属性noC或dict。在右侧选择它之后,您就有了数据模型检查器。在Xcode中打开xcdatamodel,然后选择属性noC或dictmply检查一下。很棒的呼叫!这将在iOS 6上检索单个条目的时间减少到大约50-200毫秒。计数条目的时间几乎没有变化。有没有关于加快速度的建议?我想我可以在
    dict
    noC
    的每个可能组合上硬连线条目的数量,如果需要的话,这将回复快速查找即可完成该步骤。另一个提示:您可以使用NSFetchedResultsController只查询一次,并将其保留到应用程序终止。这样您就可以从fetchedObjects属性中选择随机对象,从而将两次调用的时间减少到~0。再次感谢。我将研究NSFetchedResultsController,或者我可以做些什么imilar:当用户更改设置时,从主数据库中提取的线索子集很少发生更改。因此,我可以将其在数组中保留一段时间,并从中随机获取。感谢您的帮助!接受答案。