CoreData 性能:基于多对多关系
Posted
技术标签:
【中文标题】CoreData 性能:基于多对多关系【英文标题】:CoreData performance: predicate on more to-many relationships 【发布时间】:2011-10-25 21:31:29 【问题描述】:使用 SQL 数据存储,我有一个这样的模型:
类别 > 项目
收藏 > 物品
品牌 > 商品
每个左侧实体与 Item 实体都有一个名为 items 的一对多关系。每一个都分别是 category、collection 和 brand 的一对一 Item 关系的倒数。
我想获取与特定集合和类别相关的至少一个项目的所有品牌对象。在自然语言中,我想要具有特定类别和特定系列的所有品牌的商品。
给定对象 Category *myCategory 和 Collection *myCollection,我用来在这样的品牌实体:
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"(ANY items.category == %@) AND (ANY items.collection == %@)",myCategory,myCollection];
我得到了正确的结果。问题是性能。太慢了!我将问题简化为三个级别!让我们考虑 ios 多级目录中的四个级别:应用程序显示可用类别,用户选择一个类别,应用程序显示该类别中的集合,用户选择一个集合,应用程序显示该集合中的品牌(以及已选择的类别),用户选择一个品牌,应用程序会显示该品牌、系列和类别中的示例材料...
老实说,我使用 NSCompoundPredicate 在每次用户选择时放入 AND 子谓词,动态构建最终谓词。但这对于问题的目的无关紧要。
sql数据存储中Item实体的对象超过30,000(30k)个,items之间使用AND关系很慢(我注意到7-10在上面的示例中显示品牌的延迟秒数)。
我会尝试:
-从类别、收藏和品牌实体中删除 items 关系
-在项目实体上,将 category、collection 和 brand 关系替换为“category_id”、“collection_id”等属性上的获取属性和“brand_id”。
-使用 keypath 或谓词来获取品牌而不使用多对多关系。
在我开始破坏和重新制作过去6个月的整个作品之前,您有什么建议吗? :)
谢谢!
【问题讨论】:
【参考方案1】:颠倒你正在寻找的逻辑。
您不是在寻找具有特定类别和特定系列的品牌;您正在寻找具有 X 类别和 Y 集合的 Item 实体。一旦您拥有该 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;
更新
Item 是关系另一端的实体,就像您在问题中所拥有的一样。 -valueForKey:
将遍历项目数组并获取关系另一端的品牌实体,并返回品牌数组。您无需添加任何内容,甚至不需要添加属性,因为它将通过 KVC 访问并且“正常工作”。
这将根据您的要求为您提供最有效的检索。由于 Item 位于每个关系的多个方面,它将保存外键,因此 SQL 不需要跨越表边界,因此应该非常快。
唯一的其他选项,我不推荐它,但您可以使用来自 Category 和 Collection 的集合,并从可变集合中获取联合。每次我尝试这个方向时,它都会比访问数据库慢。在我看来,这种逻辑最好在数据库级别完成。
【讨论】:
当我阅读您的答案时,这就是我正在尝试的!这种逻辑效率更高,但我认为它仍然可以优化。考虑到:1)有超过 30k 个项目实体,获取请求需要一段时间,例如 1 秒而不是 7 秒使用多对关系,但仍然需要很长的用户体验等待时间(用户尝试“重复” ) 2) 当您使用 [itemArray valueForKey:@"brand"] 时,您如何在 Item 实体中为品牌建模?作为财产,关系或获取的财产?在第一种情况下,我需要另一个 n 获取请求...以上是关于CoreData 性能:基于多对多关系的主要内容,如果未能解决你的问题,请参考以下文章