1

Core Data に MusicInterest という名前のエンティティがあります。これらを一度に 5000 ほど追加する必要があり、現在のプロセスでは、MusicInterest が既に存在するかどうかを照会し、存在しない場合は新しいものを作成します。

これには、各タイトルが存在するかどうかを確認するためにストアに 5000 回アクセスする必要があるようです。もちろん、挿入トリップもありますが、5000 クエリが私の速度を低下させています。

各 FacebookFriend には複数の音楽への関心があり、文字列タイトルの配列を使用してそれぞれを列挙し、次のコードを呼び出します。

これを最適化する方法はありますか?

+ (MusicInterest*) musicInterestForFacebookFriend:(FacebookFriend*)facebookFriend WithTitle:(NSString*)musicTitle UsingManagedObjectContext:(NSManagedObjectContext*)moc
{
    // query to see if there
    NSArray *matches = [self queryForMusicTitle:musicTitle moc:moc];

    if (([matches count] >= 1)) {
        // NSLog(@"Music already in database");
        MusicInterest *existingMusic = [matches lastObject];
        [existingMusic addLikedByObject:facebookFriend];
        return [matches lastObject];
    } else {
        // create new Music Interest
        MusicInterest *newMusic = [NSEntityDescription insertNewObjectForEntityForName:@"MusicInterest" inManagedObjectContext:moc];
        newMusic.title = musicTitle;
        [newMusic addLikedByObject:facebookFriend];
        return newMusic;
    }
}

+ (NSArray *)queryForMusicTitle:(NSString *)MusicTitle moc:(NSManagedObjectContext *)moc
{
    // query to see if there
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MusicInterest"];
    request.predicate = [NSPredicate predicateWithFormat:@"title == %@", [NSString stringWithFormat:@"%@", MusicTitle]];

    NSError *error = nil;
    NSArray *matches = [moc executeFetchRequest:request error:&error];
    if (error) {
        NSLog(@"Error querying title in Music interest. Error = %@", error);
    }
    return matches;
}

アップデート:

Core Data プログラミング ガイドで提案されている設計を採用したところ、時間が 12 秒から 4 秒に短縮されました (まだ他の領域での最適化が必要です :)

このガイドにはサンプル コードの半分しか含まれていません。完全な実装を共有したいと思います。

musicArray = [[music componentsSeparatedByString:@", "] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
                if (obj1 > obj2)
                    return NSOrderedDescending;
                else if (obj1 < obj2)
                    return NSOrderedAscending;
                return NSOrderedSame;
            }];

            if (musicArray) {

                NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"MusicInterest"];
                [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"title IN %@", musicArray]];
                [fetchRequest setSortDescriptors:
                 @[[[NSSortDescriptor alloc] initWithKey: @"title" ascending:YES]]];

                NSError *fetchError = nil;
                NSArray *musicInterestMatchingTitles = [backgroundContext executeFetchRequest:fetchRequest error:&fetchError];

                if ([musicArray count] > 0) {
                    // walk musicArray and musicInterestsMatchingTitles in parallel
                    for (int i = 0; i < [musicArray count]; i++) {
                        NSString *title = musicArray[i];
                        if (i < [musicInterestMatchingTitles count]) {
                            MusicInterest *comparingMusicInterest = musicInterestMatchingTitles[i];
                            // compare each title
                            if (![title isEqualToString:comparingMusicInterest.title]) {
                                // if it doesn't exist as a ManagedObject (a MusicInterest), create one
                                MusicInterest *musicInterest = [MusicInterest createNewMusicInterestUsingManagedObjectContext:backgroundContext];
                                musicInterest.title = title;
                                [musicInterest addLikedByObject:friend];
                            } else {
                                // otherwise, just establish the relationship
                                [comparingMusicInterest addLikedByObject:friend];
                            }
                        } else {
                            // if there are no existing matching managedObjects, create one
                            MusicInterest *musicInterest = [MusicInterest createNewMusicInterestUsingManagedObjectContext:backgroundContext];
                            musicInterest.title = title;
                            [musicInterest addLikedByObject:friend];
                        }
                    }
                }
            }

        }];
        [self saveBackgroundContext:backgroundContext];
4

1 に答える 1

3

「Core Data Programming Guide」の「 Implementing Find-or-Create Efficiently」では、ここで役立つ可能性のあるパターンについて説明しています。基本的な考え方は次のとおりです。

  • 挿入/更新するアイテムのリストを、データベースにも保存されている一意の ID で並べ替えます。
  • 同じ ID でソートされた、リストの ID を持つすべてのオブジェクトをデータベースからフェッチする単一のフェッチ リクエストを実行します。
  • 次に、リストとフェッチされたアイテムの配列を並行してトラバースし、挿入する必要があるアイテムと、既に存在していて更新できるアイテムを見つけます。
于 2013-04-09T13:19:05.560 に答える