使用 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 多级目录中的四个级别:应用程序显示可用的类别,用户选择一个类别,应用程序显示该类别中的集合,用户选择一个集合,应用程序显示该集合中的品牌(以及已选择的类别),用户选择一个品牌,应用程序会显示该品牌、系列和类别中的示例 Material ...
老实说,我使用 NSCompoundPredicate 在每次用户选择时放入 AND 子谓词,动态构建最终谓词。但这对于问题的目的无关紧要。
sql数据存储中Item实体的对象超过30,000(30k)个,items之间使用AND关系很慢(我注意到7-10在上面的示例中显示品牌的延迟秒数)。
我会尝试:
-从类别、收藏和品牌实体中删除 items 关系
-在项目实体上,将 category、collection 和 brand 关系替换为“category_id”、“collection_id”等属性上的获取属性和“brand_id”。
-使用 keypath 或谓词来获取品牌而不使用多对多关系。
在我开始破坏和重新制作过去6个月的整个作品之前,你有什么建议吗?
谢谢!
Best Answer-推荐答案 strong>
颠倒你正在寻找的逻辑。
您不是在寻找具有特定类别和特定系列的品牌;您正在寻找具有 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 的集合,并从可变集合中获取联合。每次我尝试这个方向时,它都会比访问数据库慢。在我看来,这种逻辑最好在数据库级别完成。
关于ios - CoreData 性能 : predicate on more to-many relationships,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/7896151/
|