Я работаю над функцией поиска в одном из моих приложений на основе Core Data и пытаюсь собрать все советы по оптимизации поиска, чтобы получить ее как можно быстрее. Поиск должен быть достаточно быстрым, чтобы он мог выдавать почти мгновенные результаты для базы данных из 20 000+ объектов.
Что я сделал до сих пор (насколько оптимизация идет)
- Реализован метод, показанный в сеансе WWDC 2010, 137, создание ключевого объекта и создание отношения ко многим из моих основных объектов. Атрибут
name
ключевого объекта индексируется, и ключевые слова создаются во время начальной процедуры импорта путем разделения соответствующих строк в основных объектах и их нормализации (без учета регистра и диакритических знаков)
- Использование
>=
и <
двоичных компараторов вместо BEGINSWITH
и т. Д. Мой формат предиката:
SUBQUERY(keywords, $keyword, ($keyword.name >= $LB) AND ($keyword.name < $UB)).@count != 0
Где $LB
- строка нижних границ, а $UB
- верхние границы. Я создаю составной предикат AND
, используя этот формат и массив поисковых терминов.
Прямо сейчас я выполняю выборку один раз (когда пользователь печатает первую букву), используя размер пакета выборки около 20, а затем сужаю результаты поиска, используя метод NSArray -filteredArrayUsingPredicate, поскольку они продолжают печатать. Я также предварительно выбираю отношение keywords
, потому что оно используется для фильтрации. Часть, которая занимает больше всего времени, очевидно, является начальной выборкой. Заметная задержка ~ 1-2 с в библиотеке из 15 000 объектов. Профилирование времени показывает, что задержка вызывает именно выборка:
http://cl.ly/3a1b2022452M2V323f2H
Еще одна вещь, на которую стоит обратить внимание, это то, что мне нужно выбрать несколько объектов для результатов. У всех сущностей есть атрибут ranking
, но я не могу выбрать более одного одновременно, поэтому я вынужден извлекать их отдельно, объединять в один массив и затем сортировать вручную с помощью -sortedArrayUsingDescriptors
.
Любые советы о том, как ускорить это, будут с благодарностью.
РЕДАКТИРОВАТЬ: на основе предложений @ImHuntingWabbits:
После добавления объекта KeywordFirstChar
моя модель данных (упрощенная) будет выглядеть следующим образом:
Теперь возникает вопрос как мне написать предикат для Car
сущности, который выбирает на основе KeywordFirstChar
? Единственное, о чем я могу думать, это:
SUBQUERY(keywords, $keyword, $keyword.firstChar.char == %@)
, где %@
- это символ для поиска, но я не знаю, как это будет намного эффективнее, учитывая, что он все равно должен перечислять более keywords
, если только я не неверно истолковал предложения.