CoreData 性能:基于更多对多关系的预测
使用 SQL 数据存储,我有一个如下所示的模型:
Category <-->>物品
收集<-->>商品
品牌<-->> Item
每个左侧实体与 Item 实体都有名为 items 的一对多关系。每个项目分别是类别、系列和品牌一对一项目关系的逆。
我想获取所有品牌对象,其中至少有一个项目与特定集合和类别相关。用自然语言来说,我想要具有特定类别和特定系列的所有品牌的商品。
给定对象 Category *myCategory 和 Collection *myCollection,我用来在 Brand 实体上构建谓词这样:
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"(ANY items.category == %@) AND (ANY items.collection == %@)",myCategory,myCollection];
我得到了正确的结果。问题是性能。太慢了!我把问题简化了三个级别!让我们考虑 iOS 多级目录中的四个级别:应用程序显示可用类别,用户选择类别,应用程序显示该类别中的集合,用户选择集合,应用程序显示该集合中的品牌(以及已选择的类别),用户选择一个品牌,应用程序会显示该品牌、系列和类别中的示例材料...
说实话,我使用 NSCompoundPredicate 在每次用户选择时放入 AND 子谓词,动态构建最终谓词。但这对于问题的目的来说并不重要。
sql 数据存储中有超过 30,000 (30k) 个 Item 实体对象,并且在 items 关系之间使用 AND 非常慢(我注意到有 7-10 秒的滞后)在上例中显示品牌)。
我会尝试:
- 从类别、集合和品牌实体中删除 items 关系
- 在 Item 实体上,替换 category、collection 和 >品牌与“category_id”、“collection_id”和“brand_id”等属性上提取的属性的关系。
- 使用键路径或谓词来获取品牌,而不使用一对多关系。
在我开始销毁并重制过去6个月的全部作品之前,您有什么建议吗? :)
谢谢你!
Using SQL data store, I have a model like this:
Category <-->> Item
Collection <-->> Item
Brand <-->> Item
Every left-side entity has a to-many relationship named items to the Item entity. Each one is the inverse of to-one Item relationships category, collection and brand respectively.
I want to fetch all Brand objects with at least one Item in relation with a particular Collection AND a Category. In natural language, I want all the brands of items with particular category and a particular collection.
Given the objects Category *myCategory and Collection *myCollection, I use to build a predicate on the Brand entity in this way:
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"(ANY items.category == %@) AND (ANY items.collection == %@)",myCategory,myCollection];
And I get the correct results. The problem is performance. Too slow! And I simplified the question for three levels! Let's consider four levels in a iOS multilevel catalog: the app shows categories available, user select a category, the app shows collections in that category, user select a collection, the app shows brands in that collection (and the category already selected), user select a brand, the app shows for example materials in that brand,collection and category...
To be honest, i use NSCompoundPredicate to put in AND subpredicates at every user selection, building dynamically the final predicate. But this doesn't matter for the purpose of the question.
There are more than 30,000 (30k) objects of Item entity in the sql data store, and using AND between items relationship is very slow (I noticed 7-10 seconds of lag to show brands in the example above).
I would try to:
-remove items relationships from Category, Collection and Brand entites
-on the Item entity, replace category, collection and brand relationships with fetched properties on attributes like "category_id", "collection_id" and "brand_id".
-use keypath or predicates to fetch the brands without using to-many relationships.
Before I start to destroy and remake the whole work of the last 6 months, do you have any suggestion? :)
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
颠倒你正在寻找的逻辑。
您不是在寻找具有特定类别和特定系列的品牌;而是寻找具有特定类别和特定系列的品牌。您正在寻找一个具有 X 类别和 Y 集合的 Item 实体。一旦您拥有该 Item,您就可以询问其品牌:
Update
Item 是关系另一端的一个实体,就像您在你的问题。
-valueForKey:
将遍历项目数组并获取关系另一端的品牌实体,并返回品牌数组。您不需要添加任何内容,甚至不需要添加属性,因为它将通过 KVC 访问并且“正常工作”。这将根据您的要求为您提供最有效的检索。由于 Item 位于每个关系的多方,它将保存外键,因此 SQL 不需要跨表边界,因此应该非常快。
唯一的其他选择,我不推荐它,但您可以使用来自类别和集合的集合,并从可变集合中获得联合。每次我尝试这个方向时,它都会比访问数据库慢。我认为这种逻辑最好在数据库级别完成。
Reverse the logic of what you are looking for.
You are not looking for a Brand with a certain category and a certain collection; you are looking for an Item entity that has a category of X and a collection of Y. Once you have the Item you can ask it for its brand:
Update
Item is an entity on the other end of a relationship just as you have it in your question.
-valueForKey:
will go through the array of items and get the Brand entity on the other end of the relationship and give you back an array of the Brand. You do not need to add anything, not even a property since it will be accessed via KVC and will "just work".This is going to give you the most efficient retrieval based on your requirement. Since Item is on the many side of each of those relationships it will hold the foreign keys and therefore the SQL will not need to cross table boundaries and therefore should be very fast.
The only other option and I do not recommend it but you can play with the sets coming from Category and Collection and get a union from a mutable set. Every time I have experimented with that direction it was slower then going to the database. That kind of logic is best done at the database level in my opinion.