优化此Core数据请求 [英] Optimizing this Core Data request

查看:139
本文介绍了优化此Core数据请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Core Data中有一个名为MusicInterest的实体。我一次要添加5000左右的这些,我现在的过程是查询MusicInterest是否已经存在,如果没有创建一个新的。

I have an entity in Core Data named MusicInterest. I have to add 5000 or so of these at a time and my current process is to query to see if the MusicInterest exists already, if not create a new one.

似乎这需要5000次到商店去查看每个标题是否存在。还有,当然,插入旅行,但5000查询是什么正在拖慢我。

It seems this requires 5000 trips to the store to see if each title exists. There are also, of course, insert trips, but the 5000 queries is what's slowing me down.

每个FacebookFriend将有多个音乐兴趣,我枚举每个使用

Each FacebookFriend will have multiple music interests, and I enumerate through each one using an array of string titles, calling the following code.

任何想法如何优化这个?

Any ideas how to optimize this?

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

UPDATE:

我采用了核心数据编程指南中建议的设计,它将我的时间从12秒减少到4秒(仍然需要在其他领域进行一些优化)。

I employed the design suggested in the Core Data programming guide and it reduced my time from 12 seconds to 4 seconds (still needs some optimization in other areas :)

只包括一半的示例代码 - 我想我会分享我的完整实现:​​

The guide only includes half the sample code - I thought I would share my complete implementation:

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


推荐答案

实现有效地查找或创建< a在核心数据编程指南中描述了一种可能有用的模式。基本思想是:

Implementing Find-or-Create Efficiently in the "Core Data Programming Guide" describes a pattern that might be useful here. The basic idea is:


  • 对要插入/更新的项目列表进行排序,使用的唯一ID也存储在$ b

  • 执行单个获取请求,从数据库中获取从您的列表中标识的对象,按相同的ID排序。
  • 现在,并行遍历您的列表和获取的项目数组,以查找必须插入哪些项目以及哪些项目已存在并可以更新。

  • Sort your list of items that you want to insert/update by some unique id that is also stored in the database.
  • Perform a single fetch request that fetches all objects from the database that have an id from your list, sorted by the same id.
  • Now traverse your list and the array of fetched items in parallel, to find which items have to be inserted and which items already exist and can be updated.

这篇关于优化此Core数据请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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