views:

61

answers:

2

I need to store 20,000 records that are brief (map identifiers to names) and allow the user to search for one either by ID or name in a UISearchBar.

Approach 1 (Core Data): To conserve memory, I tried implementing this with CoreData with SQLite as the backend but found that storing 20,000 records is slow when the initial import is done. Then, as the user types in the UISearchViewBar letter by letter, the response is also noticeably slow.

Approach 2 (NSMutableArray): When I implemented the same thing in memory using NSMutableArray, the response time on the UISearchBar is very quick.

In the first approach, only a small subset of records is in memory at a time but the response time is slow. In the 2nd approach, The 20,000 items take up just 700KB (under a MB) in memory and the response time is fast.

Since Core Data provides persistant storage and makes querying very flexible with predicates, I'd like to use if it possible. Does anyone have suggestions on if there's a way of to still use Coredata but get quicker results?

Thanks

+1  A: 

Doing keystroke queries on CoreData is just not a good idea.

CoreData was not meant to be hit that hard repeatedly. You have to remember the device that's actually running this database. Put CoreData on a 10 year old desktop and see how fast it runs.

Also, I am pretty sure there is a way to use NSPredicate with NSArrays... no links for you but I think I've seen it done before.

Also yes, the initial import into CoreData is bone crushingly slow. IIRC, it's 2 separate queries per CoreData record creation.

If you want to lower the memory consumption, just call up what you need in the objects to do the searching, then pull the whole object when you actually need it.

Jasconius
Thanks for your opinion. I wasn't dong NSPredicate with NSArrays -- just with Core Data fetch. :)
Paul
I know. But I am saying you can, because that's not a bad way to do searching.
Jasconius
Sorry, thanks...I'm currently doing a for loop and doing string matching on the ID -- would also like to do string matching on the array. A for loop is probably not efficient so I'll see if I can somehow presort the array and do something more clever.
Paul
+2  A: 

Why not do both? Use Core Data for persistence. Pre-fetch the managedObjectID and properties into in-memory caches that you can use for searching with the search bar. When the item is selected, you can use the managedObjectID to fetch the Entity from the MOC.

Use NSArray's filteredArrayUsingPredicate: and NSMuatableArray's filterUsingPredicate

falconcreek
Very good idea. I didn't know you could perform filtering on NSMutableArrays...Thank you
Paul
Thank you. I tried using filteredArrayUsingPredicate yesterday. Unfortunately, because its a big array with 20,000 elements, the speed of execution keystroke by keystroke is a bit slow. Is there a way I could use an NSDictionary instead of an array to search for keys that are near matches as well. This would probably be a lot faster than traversing an array since keys are indexed by key name.
Paul
Is the array sorted? Use the mutable `fiterArrayUsingPredicate`. This will cause each subsequent search to work with a smaller set. The alternative is to "denormalize" your data in Core Data and have columns for each character. You cannot search dictionary keys for partial matches.
falconcreek