0

単語と手がかりのリストにアクセスするワードゲームアプリがあります。これは約10万エントリです。データベースはアクセスされるだけで、変更されることはありません。SQLメソッドを使用してアプリを構築しましたが、iOS 6ではかなりうまく機能しますが、データベースから新しい手がかりを取得する時間はiOS5では非常に遅くなります。

  • iOS 5は、SQLを使用して100Kから1つのレコードを取得するのに、約12秒かかります。
  • iOS 6は、SQLを使用して100Kから1つのレコードを取得するのに、約700〜1000ミリ秒かかります。

これらは両方とも32GBのiPodTouchに搭載されています。

このパフォーマンスを考慮して、CoreDataを使用してバージョンを作成しました。私のアプローチでは、最初にクエリに適合するレコードをカウントし、次にランダムに1つを選択することで、ランダムなデータベースエントリを取得します。コードは次のとおりです。私が読んだすべてのことは、コアデータがより高速になることを示唆していました:

  • iOS 5では、レコードのカウントに約4秒かかり、それらのレコードの1つを取得するには約50〜1500ミリ秒かかります。合計時間は約5秒です。
  • iOS 6では、レコードのカウントに2秒強かかり、それらのレコードの1つを取得するには約300〜500ミリ秒かかります。合計約3秒。

そのため、コアデータはiOS 5では高速ですが、iOS6ではSQLと比較して低速です。いずれにせよ、私に関する限り、パフォーマンスは遅すぎます。オーバーヘッドは以下に示すメソッドから発生することを知っています(Core Dataバージョンの場合)。したがって、2つの質問:

  1. この問題を理解し、パフォーマンスを向上させることを目的とした、この問題に関する一般的なアドバイスはありますか?
  2. 具体的には、以下に追加されているCore Dataコードについてはどうでしょうか。速度を落とすような愚かなことをしたことがありますか?または、スピードアップするために追加する必要があるものはありますか?これは、CoreDataでの私の最初の試みです。

ありがとう。

- (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;
}
4

1 に答える 1

0

エンティティ内のnoC属性やdict属性にインデックスを追加してみてください。クエリ時間が短縮される可能性があります。

于 2012-10-27T18:42:21.770 に答える