轉自 http://news.ipadown.com/14358
(參考文章:http://blog.slalom.com/2010/01/08/splitting-an-entity-in-a-coredata-migration/)
最近自己做的背單詞軟體,在之前的設計上有一個非常大的缺陷就是把單詞讀音的語音檔案放在資料庫裡面了,而且作為word表裡面的一個欄位儲存。一開始測試的時候沒有什麼大問題,但是單詞越來越多之後查詢就變得非常之慢。後面自己加上的一些功能都要頻繁地對比資料庫,所以做了一個最佳化就是在core data fetch request裡面指定要擷取的欄位,在這裡排除讀音欄位的話,查詢就非常快了,尤其當我把單詞本身的string做了index之後。但是代碼就很難看了。
core data裡面的講到類似情況的最佳化時說,需要把大資料檔案建立一個Entity獨立出來,然後和以前的Entity建立一對一關聯性。然而"Core Data Model Versioning and Data Migration Programming"這篇文檔完全忽略了怎麼樣拆分Entity這塊內容,今天搜到了一篇文章才知道怎麼做。
以下就是一個示範,基於Xcode產生的core data模板程式,並且我假定你已經知道最基本的Model versioning和mapping object的知識。
原始的Model是這樣的:
假設我們現在的目標是把address分離到一個獨立的entity中去。
現在建立立一個Model Version,假設命名為version2,把它搞成這樣:
這樣,就把address分離出去了。
接下來要做Migration了,建立一個Mapping Model檔案:
根據嚮導,將source設定為原始的Model檔案,target設定為新的Model檔案。然後Xcode會產生如下的Mapping檔案:
在這個檔案基礎上,我們只要稍作修改就能完成了。
首先把ENTITY MAPPING下面的Address重新命名為EventToAddress(這步可做可不做),然後在右側邊欄中的Entity Mapping中,設定Source為Event:
接下來改address的Value Expression為$source.address 如下:
然後在左邊的ENTITY MAPPINGS欄中切換到EventToEvent,選中Relation Mappings中的address,在右側邊欄中設定Key Path為$source,設定Mapping Name為EventToAddress(如果剛才沒改名,就用剛才的名字)。
然後設定model的current version為version2:
最後一步,在程式中初始化NSPersistentStoreCoordinator的地方,加上NSMigratePersistentStoresAutomaticallyOption的選項,代碼類似如下:
1 _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
2 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
3 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
4 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
5 if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
6 NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
7 abort();
8 }
最後,運行程式,在程式初始化的時候,就會自動做migration了。如果要migration的資料量非常大,就會非常的慢。
完整原始碼見:https://gitcafe.com/hikui/iOS-Example/tree/master/CoreDataMigrationDemo