I am working on a project with the following many-to-many model:
Book: can have multiple tags (book.tags) Tag: can include a lot of books (tag.books)
i found that when a book is already in database and i just simply want to add a tag to that book by doing [bookMO addTagsObject:tag]
, i will get a fault in book.tags. using the instrument, i found the core data is trying to do "[NSObject(NSKeyValueObserver(Notification) willChangeValueForKey:withSetMutation:usingObjects]
".
i also checked the actual sql getting executed and i found:
annotation: to-many relationship fault "tags" for objectID 0x20140b00
fulfilled from database.
and then a sql query that returns all the tags that contain this book. i found internally core data use a join table of Book and Tag. the primary key of that join table is simply a combination of book_id and tag_id
. That joint table is not indexed. And to get all the tags that contain a book, it seems to be (i am not sure here) traversing all the rows in that joint table and therefore this operation is very expensive.
i think what is happening in my app now is, every time i want to add a tag to a book, i will have to do that linear scan in the joint table. The overall complexity is O(N^2)
because each operation will do a linear scan in the join table. And I am having 10k books now and the performance is not so good..
is there any way i can avoid that tags
fault triggered by kvo? or is there any way i can implement my own join table that can return the result in O(1)
by indexing?
-Erben