使用核心数据时可能有复杂的索引吗?

我正在研究一个iOS闪存卡风格的学习应用程序,在加载时需要从Core Data获取一堆数据。 但是我需要的数据是一个相当特定的实体子集,基于用户设置,所以有多个谓词涉及testing等价性。 我发现这些提取超慢,基于对SQLite的研究,我认为索引将是一个很好的select。

现在,我明白(很大程度上来自阅读其他stackoverflow问题),SQLite和核心数据是两个不同的,基本上正交的东西,不应该混淆。 但是我的理解是,你应该通过Core Data来做任何types的数据库工作和调整; 在应用程序中优化或devise对象永久性时,您不应该尝试绕过并直接使用SQLite。

但是我唯一可以在Core Data中find索引的就是模型中每个属性的一个“索引”checkbox。 这只是没有做我想要的那种优化。

以下是抓取请求,目前是:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"SKUserItem" inManagedObjectContext:context]; fetchRequest.entity = entity; NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"next" ascending:YES] autorelease]; fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:6]; [predicates addObject:[NSPredicate predicateWithFormat:@"next < %f", now() + (60.0*60.0*24.0)]]; [predicates addObject:[NSPredicate predicateWithFormat:@"next > %f", nextOffset]]; [predicates addObject:[NSPredicate predicateWithFormat:@"user == %@", user]]; [predicates addObject:[NSPredicate predicateWithFormat:@"langRaw == %d", lang]]; NSArray *stylePredicates = [NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"styleRaw == %d", SK_SIMP_AND_TRAD], [NSPredicate predicateWithFormat:@"styleRaw == %d", self.style], nil]; [predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:stylePredicates]]; if([self.parts count] == 4 || (self.lang == SK_JA && [self.parts count] == 3)) ; // don't have to filter by parts; they're studying all of them else { NSMutableArray *partPredicates = [NSMutableArray arrayWithCapacity:[self.parts count]]; for(NSString *part in self.parts) [partPredicates addObject:[NSPredicate predicateWithFormat:@"partRaw == %d", partCode(part)]]; [predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:partPredicates]]; } NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; fetchRequest.predicate = compoundPredicate; 

所以基本上这个提取是按照下一个(给定项目到期的时间)sorting的,并且筛选用户名,研究的语言,研究的风格(中文简化和传统)以及正在研究的部分,阅读或定义),只能在“下一个”范围内进行提取。 下面是我从调整和摆弄中学到的一些简短的列表:

  1. 它总是扫描整个桌子,或似乎。 虽然下一个索引,即使我强迫它search一个我知道的范围将什么都不会返回,它仍然需要几秒钟才能完成。
  2. 谓词,任何数量的谓词都会使这个过程变慢。 如果我删除一些,但不是全部,这是一样慢。 如果我删除所有的谓词(从而打破了应用程序),那么速度更快。
  3. 速度很大程度上取决于表中总共有多less个UserItem。 有更多的项目,这是越慢。 有些人可能有成千上万的项目,那么这个取指可能需要10秒才能完成。 这导致我的应用程序暂停尴尬。
  4. 下一个值的上限并不是因为我们需要它,而是因为它加快了取回的速度。
  5. 让查询返回一个字典中的属性的子集(而不是整个托pipe对象),并且懒得提取其余部分的速度会更快,但是仍然不够快。

我来自Google App Engine,所以我习惯了他们在那里提供的索引。 基本上我想要这样的索引,但通过核心数据应用到SQLite。 我发现有关在SQLite中添加索引的信息,我想要的types,但通过核心数据做这种索引,我找不到任何信息。

你想要的是Core Data在iOS 5.0及更高版本中支持的复合索引

您可以在Xcode中进行设置: 实体检查器有一个索引部分,或者如果您要在代码中创buildNSEntityDescription ,请使用-setCompoundIndexes:

如果你使用Xcode,你可以在Indexes部分添加一行

 next,user,langRaw 

这样SQL可以使用索引来查询。

核心数据有一个SQL后端。 你这样做的方式是将一个表(一个实体的一部分)中的所有数据都找出来,并且find你正在查找的对象将需要search所有行,就像你说的那样。

在您的数据模型中,您需要将您正在search的一些属性分解为其他实体。 试着让它更基于对象,并考虑你将要search的内容。

例如,有一个用户,语言实体,也许是一个教训或任何时间为基础的东西,你正在寻找。

Lesson实体对于语言和与用户的单一关系具有多种关系。 (或者如果多于一个用户上课的话,也是很多的)

然后,要查找用户的数据,请提取该用户,并调查她的语言或课程属性以了解更多信息。

要查找学习语言的用户列表,请提取您正在查找的语言实体并调查用户的属性。