核心数据:子查询性能问题

发布于 2024-11-02 12:28:16 字数 429 浏览 1 评论 0原文

我一直在尝试查看是否有任何方法可以提高以下谓词的性能:

[NSPredicate predicateWithFormat:@"A=%@ and SUBQUERY($self.words,$k,$k.keyword IN %@).@count==%d", 
  <value for A>, 
  keywordList, 
  [keywordList count]];

我想做的是返回 A 的所有记录,这些记录的关键字全部包含在提供的数组 (keywordList )。我有一个大约有 2000 条记录的小型数据库。但是,每个实体的关键字范围为 40-300 个关键字。关键字表示为从 A 到称为关键字的实体的多对关系。上面的查询有效,但在我的 iPhone4 上运行大约需要 7 秒。我想看看我能做些什么来将其缩小到亚秒级响应。

谢谢, 迈克尔

I've been trying to see if there is any way I can improve on the performance of the following Predicate:

[NSPredicate predicateWithFormat:@"A=%@ and SUBQUERY($self.words,$k,$k.keyword IN %@).@count==%d", 
  <value for A>, 
  keywordList, 
  [keywordList count]];

What I'm trying to do is return all the records of A that have keywords that are ALL contained in the supplied array (keywordList). I have a small database of about 2000 records. However, the keywords for each Entity ranges from 40-300 keywords. The keywords are represented as a to-Many relationship from A to an entity called Keywords. The above query works but takes about 7 seconds to run on my iPhone4. I want to see what I can do to shrink that down to a sub-second response.

Thanks,
Michael

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

入画浅相思 2024-11-09 12:28:16

这并不能完全解决问题,因为从 fetchedObjs 的交集返回的结果不正确。它不保证所有“A”对象都包含所有提供的关键字。事实上,返回的是一个空列表,整个过程实际上需要更长的时间。

我的模型或之前的答案一定有问题。我没有得到我期望的结果。返回“A”列表的一种替代方法是返回“A”的 ManagedObjectID 列表。 [mo valueForKey: (NSString *)] 返回关系的对象。

注意:我最初匿名发布这个问题,以为我已经登录,所以我似乎无法评论任何人的答案。

This doesn't quite solve the problem as the results that come back from intersection of the fetchedObjs is not correct. It doesn't guarantee that all the 'A' objects contain all the supplied keywords. In fact, what comes back is an empty list and the entire process actually takes longer.

Something must be wrong with my model or the previous answer. I'm not getting the results I'm expecting. One alternative to returning a list of 'A' would be to return a list of ManagedObjectIDs of 'A'. [mo valueForKey: (NSString *)] returns the object of the relationship.

Note: I originally posted this question anonymously thinking I was logged in, so i can't seem to comment on anybody's answer.

赢得她心 2024-11-09 12:28:16

我认为你正在倒退地处理这个问题。如果您有关键字,则应搜索 Keyword 对象,然后遍历它们的 A 关系以查找相关的 A 对象。 然后检查关系集中是否有重叠。

因此,类似:

NSFetchRequest *fetch=//...set up fetch
[fetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[fetch setPredicate:p];
NSArray *fetchedObj=//... execute fetch

NSMutableSet *inCommon=[NSMutableSet setWithCapacity:[fetchedObjs count]];
for (NSManagedObject *mo in fetchedObjs){
  if ([inCommon count]==0){
    [inCommon addObjects:[mo valueForKey:@"aRelationshipName"]];
  }else{
    [inCommon intersectSet:[mo valueForKey:@"aRelationshipName"]];
  }
}

... inCommon 将包含一组共享所有关键字的所有唯一 A 对象。

更新:

来自OP作者:

这并不能完全解决问题
作为返回的结果
fetchedObjs 的交集不是
正确的。它并不能保证所有
'A' 对象包含所有
提供的关键字。

好吧,我们采取另一种策略。假设您有一个看起来像这样的数据模型:

A {
    keywords<<-->>Keyword.as
}

Keyword{
    keyword:string
    as<<-->>A.keywords
}

那么这样的东西应该可以工作:

NSFetchRequest *keyWordFetch=//...set up fetch
[keyWordFetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[keyWordFetch setPredicate:p];
NSArray *fetchedKeywords=//... execute keyWordFetch


NSFetchRequest *entityAFetch=//...set up fetch
[entityAFetch setEntity:A_entity];
NSPredicate *pred=[NSPredicate predicateWithFormat:@"ALL keywords IN %@", fetchedKeywords);
[entityAFetch setPredicate:pred];
NSArray *fetchedAs=//... execute fetch

I think you are approaching the problem backwards. If you have the keywords, you should search for the Keyword objects and then walk their A relationships to find the related A objects. Then check for overlap in the relationship sets.

So something like:

NSFetchRequest *fetch=//...set up fetch
[fetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[fetch setPredicate:p];
NSArray *fetchedObj=//... execute fetch

NSMutableSet *inCommon=[NSMutableSet setWithCapacity:[fetchedObjs count]];
for (NSManagedObject *mo in fetchedObjs){
  if ([inCommon count]==0){
    [inCommon addObjects:[mo valueForKey:@"aRelationshipName"]];
  }else{
    [inCommon intersectSet:[mo valueForKey:@"aRelationshipName"]];
  }
}

... inCommon would then contain a set of all unique A objects that shared all the keywords.

Update:

From OP author:

This doesn't quite solve the problem
as the results that come back from
intersection of the fetchedObjs is not
correct. It doesn't guarantee that all
the 'A' objects contain all the
supplied keywords.

Okay, lets take another tack. Assuming you have a data model that looks something like this:

A {
    keywords<<-->>Keyword.as
}

Keyword{
    keyword:string
    as<<-->>A.keywords
}

Then something like this should work:

NSFetchRequest *keyWordFetch=//...set up fetch
[keyWordFetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:@"keyword IN %@",keywords];
[keyWordFetch setPredicate:p];
NSArray *fetchedKeywords=//... execute keyWordFetch


NSFetchRequest *entityAFetch=//...set up fetch
[entityAFetch setEntity:A_entity];
NSPredicate *pred=[NSPredicate predicateWithFormat:@"ALL keywords IN %@", fetchedKeywords);
[entityAFetch setPredicate:pred];
NSArray *fetchedAs=//... execute fetch
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文