Производительность NSSortDescriptor? - PullRequest
1 голос
/ 08 октября 2011

У меня есть база данных на базе SQLite, состоящая примерно из 4000 строк, связанных с базовыми данными.Модель представляет собой простой обзор -> деталь модели.Каждый обзор (с заголовком и подзаголовком) имеет отношение к детали, которая содержит подробную информацию.Для просмотра этих данных я реализовал UITableView с NSFetchedRequestController.

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"registered_name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sort];

NSPredicate *filterPredicate = nil;
NSString *sectionName = nil;
NSString *cacheName = nil;

NSFetchedResultsController *aFetchedResultsController = nil;
aFetchedResultsController.delegate = self;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

[fetchRequest setFetchBatchSize:20];
[fetchRequest setSortDescriptors:sortDescriptors];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Info" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

[fetchRequest setPredicate:filterPredicate];
aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:sectionName cacheName:cacheName];

NSError *error = nil;
if (![aFetchedResultsController performFetch:&error]) 
  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  abort();
}

[fetchRequest release];
[sort release];
return aFetchedResultsController;`

Я реализовал все, и это работает, но работает медленно.В частности, я обеспокоен запуском приложения.

Этот запрос замедляет время запуска (флаг отладки SQL в XCode):

CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZREGISTERED_NAME
CoreData: annotation: sql connection fetch time: 0.8773s 
CoreData: annotation: total fetch execution time: 0.8976s for 4302 rows. 

Это происходит сразу после выполнения executeFetch.казнены.Почему Core Data чувствует необходимость получить и отсортировать все 4302 строки моей базы данных?Если я установлю setLimit на небольшое значение, скажем 20, конечно, все будет работать очень быстро, но я получу только 20 результатов.С другой стороны, теперь у меня есть setBatchSize, который прекрасно работает, и я могу видеть операторы SELECT в консоли отладки, когда я прокручиваю табличное представление.Но он по-прежнему сортирует 4302 строки при запуске, что, как мне кажется, неоправданно замедляет время запуска приложения.

Я намерен реализовать нормализованную сортировку строк и селектор caseInsensitiveNumericCompare в NSSortDescriptor, согласно примеру кода Apple WWDC 2010, номне кажется, я упускаю что-то простое здесь.

Обновление:

Кажется, что я не могу использовать пользовательский селектор caseInsensitiveNumericCompare: с NSSortDescriptor, так как я использую SQLite в качестве базы данных.Я действительно не понимаю, что еще я могу сделать, чтобы ускорить это.Может быть, SQLite будет сортировать быстрее с укороченной и нормализованной строкой, вот что я пытаюсь сделать дальше.

Обновление 2:

С нормализованной строкой (без других букв или символов, кроме AZ и 0-9), время запуска составляет около 0,7 с.Не большое сокращение.Последнее, что я пытаюсь - это предварительно отсортировать базу данных, а затем назначить добавочные идентификаторы для строк.В NSSortDescriptor я буду сортировать по этому числовому идентификатору.Согласно моим тестам SQL, это должно быть примерно в 7 раз быстрее.

1 Ответ

0 голосов
/ 10 октября 2011

Я решил свою проблему.Это просто напоминание для тех, кто может столкнуться с подобными проблемами. Ошибка, которую я сделал, не создавала индексы для обязательных полей на стороне базы данных. Я просто щелкнул опцию «indexed» в моей модели в XCode.Очевидно, это НЕ создает никаких индексов, если вы сами предоставили файл .sqlite.

После любопытного случая запуска, когда Core Data решила создать базу данных для меня, я увидел, что эти предложения SQL выполнены:

2011-10-08 19:49:40.572 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZREGISTERED_NAME_INDEX ON ZINFO (ZREGISTERED_NAME)
2011-10-08 19:49:40.586 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZFIRSTLETTER_INDEX ON ZINFO (ZFIRSTLETTER)
2011-10-08 19:49:40.598 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZNAME_INDEX ON ZINFO (ZNAME)
2011-10-08 19:49:40.610 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZN_SL_NAME_INDEX ON ZINFO (ZN_SL_NAME)
2011-10-08 19:49:40.622 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZN_REGISTERED_NAME_INDEX ON ZINFO (ZN_REGISTERED_NAME)
2011-10-08 19:49:40.635 App[1717:307] CoreData: sql: CREATE INDEX ZINFO_ZDETAILS_INDEX ON ZINFO (ZDETAILS)

После того, как я реплицировал эти индексы в моей собственной базе данных, ситуация значительно ускорилась:

CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZREGISTERED_NAME
CoreData: annotation: sql connection fetch time: 0.1315s
CoreData: annotation: total fetch execution time: 0.1568s for 4161 rows.

Я чрезвычайно доволен этими цифрами.Но так как я теперь предварительно отсортировал свою базу данных, я могу использовать номер для NSSortDescriptor.Это подводит меня к:

CoreData: sql: SELECT 0, t0.Z_PK FROM ZINFO t0 ORDER BY t0.ZID
CoreData: annotation: sql connection fetch time: 0.0677s
CoreData: annotation: total fetch execution time: 0.0890s for 4161 rows.

То есть чуть меньше 9 сотых секунды, а не 9 десятых секунды.

...