Я работаю над обучающим приложением в стиле флеш-карт для iOS, которое при загрузке должно получить кучу данных из Core Data. Но данные, которые мне нужны, являются довольно специфическим подмножеством сущности, основанным на настройках пользователя, поэтому существует несколько предикатов, проверяющих эквивалентность. Я обнаружил, что эти запросы выполняются очень медленно, и, основываясь на исследовании SQLite, я думаю, что индекс будет хорошим выбором.
Теперь я понимаю (в основном из чтения других вопросов на stackoverflow), что SQLite и Core Data - это две разные, в основном ортогональные вещи, которые не следует путать. Но я также понимаю, что вы должны работать через Core Data для выполнения любой работы с базой данных и настройки; вы не должны пытаться обойти и работать напрямую с SQLite при оптимизации или проектировании постоянства объектов в вашем приложении.
Но единственное, что я могу найти для индексов в Core Data - это один флажок "индексировать" для каждого атрибута в модели. И это просто не дает той оптимизации, которую я ищу.
Вот запрос на выборку в настоящее время:
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;
Итак, по существу, что делает эта выборка, это сортировка по next (время, когда данный элемент должен быть выполнен) и фильтр по имени пользователя, изучаемому языку, изучаемому стилю (в китайском есть упрощенный и традиционный) и изучаемым частям (письмо, тон, чтение или определение), и только выборка в диапазоне "next". Вот краткий список того, что я узнал, настраивая и возившись с этим:
Я пришел из Google App Engine, поэтому я привык к индексам, которые они там предоставляют. По сути, мне нужен подобный индекс, но примененный к SQLite через Core Data. Я нашел информацию о добавлении индексов в SQLite, таких, какие мне нужны, но о том, как сделать подобный индекс через Core Data, я не могу найти никакой информации.