I am working on a search function in one of my Core Data-based applications, and I'm trying to collect all the search optimization tips to get them as fast as possible. The search should be fast enough so that it can deliver almost instant results for a database of 20,000 objects.
What I have done so far (as optimization)
- Implemented the technique shown in session 137 of WWDC 2010, creating a keyword object and creating a relationship to many of my main object objects. The entity
name attribute is indexed, and keywords are created during the initial import procedure, separating the corresponding lines in the main entities and normalizing them (devoid of cases and diacritics). - Using
>= and < binary comparators instead of BEGINSWITH etc. My predicate:
SUBQUERY(keywords, $keyword, ($keyword.name >= $LB) AND ($keyword.name < $UB)) .@count != 0
Where $LB is the string of lower bounds and $UB is the upper bound. I create a compound AND predicate using this format and an array of search terms.
Now I fetch one time (when the user types the first letter), using the batch size of about 20, and then narrowing down the search results using the NSArray -filteredArrayUsingPredicate method as they continue to print. I also prefetch the attitude of keywords because it is used for filtering. Obviously, the part that takes the most time is the initial sample. There is a noticeable delay of ~ 1-2s in the library of about 15,000 objects. Time profiling shows that actually sampling causes a delay:
http://cl.ly/3a1b2022452M2V323f2H
Another thing worth noting is that I have to get multiple objects for the results. All entities have a ranking attribute, but I canβt get it more than once, so I have to retrieve them separately, merge them into one array and sort manually using -sortedArrayUsingDescriptors .
Any advice on how to speed this up would be greatly appreciated.
EDIT: based on @ImHuntingWabbits suggestions:
After adding the KeywordFirstChar object KeywordFirstChar my data model (simplified) will look like this:

Now questions , how would I write a predicate for a Car object that selects based on KeywordFirstChar ? The only thing I can think of is this:
SUBQUERY(keywords, $keyword, $keyword.firstChar.char == %@) where %@ is the search character, but I donβt know how it would be much more efficient, given that it still needs to list keywords if I misinterpreted the sentences.