У меня есть серия NSFetchedResultsControllers, управляющих некоторыми представлениями таблиц, и их производительность на устройстве была ужасной, порядка секунд. Поскольку все это выполняется в основном потоке, оно блокирует мое приложение при запуске, что не очень хорошо.
Я исследовал и оказалось, что предикат является проблемой:
NSPredicate *somePredicate = [NSPredicate predicateWithFormat:@"ANY somethings == %@", something];
[fetchRequest setPredicate:somePredicate];
Т.е. объект извлечения, называемый "вещами", имеет отношение "многие ко многим" с сущностью "нечто". Этот предикат является фильтром, который ограничивает результаты только вещами, имеющими отношение к определенному «чему-то».
Когда я удалил предикат для тестирования, время выборки (начальный executeFetch: вызов) уменьшилось (для некоторых крайних случаев) с 4 секунд до 100 мс или меньше, что является приемлемым. Однако меня это беспокоит, поскольку это сводит на нет многие преимущества, которые я надеялся получить с помощью Core Data и NSFRC, которые в остальном кажутся мощным инструментом.
Итак, мой вопрос, как я могу оптимизировать эту производительность? Я неправильно использую предикат? Должен ли я как-то изменить модель / схему? И какие еще есть способы это исправить? Можно ли ожидать такого снижения производительности? (Есть порядка сотен объектов размером <1 КБ.) </p>
РЕДАКТИРОВАТЬ С ДЕТАЛЯМИ:
Вот код:
[fetchRequest setFetchLimit:200];
NSLog(@"before fetch");
BOOL success = [frc performFetch:&error];
if (!success) {
NSLog(@"Fetch request error: %@", error);
}
NSLog(@"after fetch");
Обновленные журналы (ранее у меня были некоторые неэффективности приложений, снижающие производительность. Это обновленные журналы, которые должны быть настолько близки к оптимальным, насколько это возможно в моей текущей среде):
2010-02-05 12:45:22.138 Special Ppl[429:207] before fetch
2010-02-05 12:45:22.144 Special Ppl[429:207] CoreData: sql: SELECT DISTINCT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 LEFT OUTER JOIN Z_1THINGS t1 ON t0.Z_PK = t1.Z_2THINGS WHERE t1.Z_1SOMETHINGS = ? ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:45:22.663 Special Ppl[429:207] CoreData: annotation: sql connection fetch time: 0.5094s
2010-02-05 12:45:22.668 Special Ppl[429:207] CoreData: annotation: total fetch execution time: 0.5240s for 198 rows.
2010-02-05 12:45:22.706 Special Ppl[429:207] after fetch
Если я сделаю то же самое без предиката (закомментировав две строки в начале вопроса):
2010-02-05 12:44:10.398 Special Ppl[414:207] before fetch
2010-02-05 12:44:10.405 Special Ppl[414:207] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:44:10.426 Special Ppl[414:207] CoreData: annotation: sql connection fetch time: 0.0125s
2010-02-05 12:44:10.431 Special Ppl[414:207] CoreData: annotation: total fetch execution time: 0.0262s for 200 rows.
2010-02-05 12:44:10.457 Special Ppl[414:207] after fetch
20-кратная разница во времени. 500 мс не так уж и велики, и, кажется, нет способа сделать это в фоновом режиме или оптимизировать каким-либо другим способом, о котором я могу думать. (Помимо перехода в бинарное хранилище, где это становится не проблема, так что я мог бы это сделать. Производительность бинарного хранилища постоянно составляет ~ 100 мс для вышеуказанного запроса с 200 объектами.)
(я вложил здесь еще один вопрос, который я сейчас удалил ).