Как улучшить производительность основных данных?

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

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

Мои основные данные поддерживаются хранилищем данных 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];

Ответы

Ответ 1

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

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

word > "term" AND word < "Терн"

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

У Apple есть Основные данные, который объясняет это, включая пример кода. Код примера содержит класс, который обрабатывает нормализацию строки (I.e. Removing case) и увеличивает последний символ слова в режиме unicode.

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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