CoreData性能:预测更多对多关系

时间:2011-10-25 21:31:29

标签: ios performance core-data nspredicate one-to-many

使用SQL数据存储,我有一个这样的模型:

类别< - >>项目

收藏< - >>项目

品牌< - >>项目

每个左侧实体都有一个与Item实体名为 items 的多对多关系。每个项目关系分别为一个项目关系类别集合品牌

我想获取所有Brand对象,其中至少有一个Item与特定Collection和Category相关。在自然语言中,我希望所有品牌的品牌都有特定的类别和特定的系列。

鉴于对象 Category * myCategory Collection * myCollection ,我用来构建一个谓词品牌实体就这样:

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"(ANY items.category == %@) AND (ANY items.collection == %@)",myCategory,myCollection]; 

我得到了正确的结果。问题是性能。太慢了!我简化了三个级别的问题!让我们考虑iOS多级目录中的四个级别:应用程序显示可用类别,用户选择类别,应用程序显示该类别中的集合,用户选择集合,应用程序显示该集合中的品牌(以及已选择的类别),用户选择一个品牌,该应用程序显示该品牌,集合和类别中的材料......

老实说,我使用NSCompoundPredicate在每个用户选择中输入AND subpredicates,动态构建最终谓词。但这对问题的目的无关紧要。

在sql数据存储中有超过30,000(30k)个 Item 实体的对象,并且在项目之间使用AND 关系非常慢(我注意到7-10在上面的例子中显示品牌的滞后时间。)

我会尝试:

- 从类别,收藏和品牌推广中删除项目关系

- 在项目实体中,将类别集合品牌关系替换为“category_id”,“collection_id”等属性的已获取属性和“brand_id”。

- 使用keypath或谓词来获取品牌而不使用多对多关系。

在我开始摧毁和重拍过去6个月的整个工作之前,你有什么建议吗? :)

谢谢!

1 个答案:

答案 0 :(得分:2)

颠倒你正在寻找的逻辑。

您不是在寻找具有特定类别和特定集合的品牌;您正在寻找一个具有X类别和Y集合的Item实体。一旦您拥有该项目,您可以询问其品牌:

id myCategory = ...;
id myCollection = ...;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Item"];
[request setPredicate:[NSPredicate predicateWithFormat:@"category == %@ && collection == %@", myCategory, myCollection]];

NSError *error = nil;
NSArray *itemArray = [moc executeFetchRequest:request error:&error];
NSAssert2(!error || itemArray, @"Error fetching items: %@\n%@", [error localizedDescription], [error userInfo]);

NSArray *brands = [itemArray valueForKey:@"brand"];
return brands;

更新

项目是关系另一端的实体,正如您在问题中所拥有的那样。 -valueForKey:将遍历项目数组,并在关系的另一端获取Brand实体,并返回一个品牌数组。您不需要添加任何内容,甚至不需要添加任何属性,因为它将通过KVC访问并且“只是工作”。

这将根据您的要求为您提供最有效的检索。由于Item位于每个关系的许多方面,因此它将保存外键,因此SQL不需要跨越表边界,因此应该非常快。

唯一的另一种选择,我不推荐它,但你可以使用来自Category和Collection的集合,并从一个可变的集合中获得一个联合。每次我尝试这个方向时,它都会慢慢进入数据库。在我看来,这种逻辑最好在数据库级别完成。