Как улучшить производительность Core Data? - PullRequest
14 голосов
/ 16 августа 2010

В моем приложении есть UISearchBar, позволяющий пользователю вводить ключевые слова для поиска. Каждое нажатие клавиши выполняет запрос базовых данных, чтобы отобразить результаты в виде изменения текста в строке поиска.

Проблема в том, что нажатия на панели поиска довольно сильно отстают ... конечно, из-за медленной выборки. Есть идеи как улучшить производительность?

Мои основные данные поддерживаются хранилищем данных sqlite, которое содержит 1000 объектов.

// searchKeyword is the string appears in UISearchBar
// Both title and author may contain several words so I can't use BEGINSWITH
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(author CONTAINS[c] %@) OR (title CONTAINS[c] %@)", searchKeyword, searchKeyword];

NSEntityDescription* entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:managedObjectContext];

NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
[request setFetchLimit:10];

NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];

[sortDescriptor release];
[sortDescriptors release];

execute request and fetch the results
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                managedObjectContext:managedObjectContext
                                sectionNameKeyPath:nil
                                cacheName:nil];
NSError* error = nil;
BOOL success = [fetchedResultsController performFetch:&error];
[request release];

Ответы [ 5 ]

18 голосов
/ 16 августа 2010

Использование CONTAINS замедляет его.Что вам нужно сделать, это создать новую таблицу под названием searchWords (или как угодно), в которой хранятся все слова в ваших заголовках, выполненные строчными буквами и с удаленными акцентами.У них есть связь, связывающая их с исходными объектами.Убедитесь, что поле слова проиндексировано.

Выполните запрос по этой таблице, но вместо использования CONTAINS или BEGINSWITH сделайте что-то вроде

word> "term" AND word <"tern" </p>

Обратите внимание, что первая строка содержит поисковый термин, а вторая - поисковый термин с увеличенным последним символом.Это позволяет Core Data использовать индекс SQL для выполнения поиска.

Apple имеет сеанс Core Data WWDC, который объясняет это, включая пример кода.Пример кода содержит класс, который обрабатывает нормализацию строки (т. Е. Удаление регистра) и приращение последнего символа слова с учетом юникода.

13 голосов
/ 17 августа 2010

Хотя рекомендация Амойры обоснована, у вас также есть проблема с дизайном.

Только первая буква, введенная в поле поиска, должна когда-либо попадать на диск. После первой буквы вам следует только уточнить результаты поиска того, что уже есть в памяти.

Вам следует отфильтровать массив, находящийся в памяти (из поиска по первой букве), используя уже имеющийся предикат, и избегать выполнения запроса на выборку, так как он не нужен.

Кроме того, если вы собираетесь искать данные, которые уже находятся в памяти (например, живут в NSFetchedResultsController), тогда весь ваш поиск должен затрагивать только объекты в памяти. Выход на диск не нужен и ужасно расточителен.

4 голосов
/ 16 августа 2010

Хотя это не ускорит запрос, размещение поиска в фоновом потоке предотвратит отставание нажатий клавиш.

2 голосов
/ 16 августа 2010

Вы можете создать trie с приращением, чтобы иметь индекс для прошлых запросов (результирующие наборы указываются конечными узлами). но это не увеличит производительность одного запроса. Вы также можете настроить систему нажатия клавиш, не делать выборку после каждого нажатия клавиши, а только после нажатия клавиши, после которого проходит временной интервал (в качестве порога) до распознавания другого нажатия

0 голосов
/ 16 августа 2010

При запуске приложения создайте полный файл и адаптируйте его при редактировании.Не используйте этот глупый предикат.Вы получаете только 1000 записей, так что это не займет много времени.

...