2013-06-11 8 views
8

Stworzyłem nowy model i zmieniono nazwę na 2 pola obiektu. Ten element nigdy nie był używany w poprzedniej wersji aplikacji, więc nie zamapowałem go na nowy zaktualizowany element w bazie danych. W związku z tym mapowanie nie odwzorowuje niczego nowego, ale migracja jest bardzo powolna (3 sekundy dla około 50 wierszy w głównej tabeli). Zastanawiam się, czy dane podstawowe tworzą nową bazę danych i usuwają starszą, i ponownie wstawiają wszystkie dane. Jest to plik dziennika migracji: http://cl.ly/3H1v252R1p1cMigracja danych podstawowych jest powolna, chociaż nie ma potrzeby migrowania

ps. Jeśli NSInferMappingModelAutomaticallyOption jest TAK, oznacza to, że mogę potencjalnie doświadczyć utraty danych, ponieważ mapowanie jest improwizowane przez podstawowe dane?

dzięki

Odpowiedz

3

Czy możesz pokazać nam swój schemat bazy danych? Domyślam się, że użyłeś w tym celu dziedziczenia przedmiotów.

Core Data implementuje dziedziczenie w magazynach SQL, tworząc pojedynczą tabelę dla jednostki nadrzędnej i dodając kolumny dla unii wszystkich pól używanych przez elementy podrzędne. Więc możesz pomyśleć, że przemianowałeś tylko dwa pola na jednej jednostce, ale Core Data musi zastosować zmiany do każdego obiektu, który dziedziczy z tego bytu lub który ma wspólnego przodka tego bytu.

W swoim konkretnym schemacie wygląda na to, że posiada się przedmiot, z którego pochodzi co najmniej Gatunek, Ścieżka Dźwięku, Studio, Dyrektor, Sklep, Film, Warunek, Region, Właściciel, AspectRatio, Rok, MyRating, Epizod, Edycja, Format, producent, scenarzysta, AudienceRating, SeenIt i Movie schodzą. Mogą być inne osoby, ponieważ czytam dziennik, a nie analizuję go automatycznie. Tak więc Core Data tworzy jedną tabelę o nazwie Item, w której przechowywane są wszystkie wystąpienia każdej z tych jednostek. Za każdym razem, gdy zmienia się którykolwiek z tych elementów (lub innych, których prawdopodobnie nie znalazłem), dane podstawowe muszą aktualizować zapisy dla wszystkich wystąpień każdego z tych elementów.

Dlatego widzisz:

CREATE TABLE ZITEM (Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, 
ZUNIQUEID INTEGER, ZCOLLECTIONSTATUS INTEGER, ZHASCOVER INTEGER, ZINDEX INTEGER, 
ZPLOTNOTE INTEGER, ZUSERVALUES INTEGER, ZPURCHASEDATEDAY INTEGER, 
ZPURCHASEDATEMONTH INTEGER, ZPURCHASEDATEYEAR INTEGER, ZRELEASEDATEDAY INTEGER, 
ZRELEASEDATEMONTH INTEGER, ZRUNTIME INTEGER, ZVIEWINGDATEDAY INTEGER, 
ZVIEWINGDATEMONTH INTEGER, ZVIEWINGDATEYEAR INTEGER, ZAUDIENCERATING INTEGER, 
ZCONDITION INTEGER, ZEDITION INTEGER, ZFORMAT INTEGER, ZLOANER INTEGER, 
ZLOCATION INTEGER, ZMYRATING INTEGER, ZOWNER INTEGER, ZSEARCH INTEGER, 
ZSEENIT INTEGER, ZSEENWHERE INTEGER, ZSERIES INTEGER, ZSTORAGEDEVICE INTEGER, 
ZSTORE INTEGER, ZYEAR INTEGER, ZRANK INTEGER, ZTYPEID INTEGER, 
ZCOLLECTIBLE INTEGER, Z3_COLLECTIBLE INTEGER, ZBIN INTEGER, ZSORTORDER INTEGER, 
ZSECTION VARCHAR, ZCLZID VARCHAR, ZCONNECTHASH VARCHAR, ZSORTTITLE VARCHAR, 
ZTITLE VARCHAR, ZACTORS VARCHAR, ZCLZMEDIAID VARCHAR, ZCURRENTVALUE VARCHAR, 
ZIMDBNUMBER VARCHAR, ZIMDBRATING VARCHAR, ZLOANDATE VARCHAR, ZLOANDUEDATE VARCHAR, 
ZPURCHASEPRICE VARCHAR, ZSTORAGESLOT VARCHAR, ZTITLEEXTENSION VARCHAR, 
ZUPC VARCHAR, ZTHEDESCRIPTION VARCHAR, ZURL VARCHAR, ZDISPLAYNAME VARCHAR, 
ZSORTNAME VARCHAR) 

To tabelę zawierającą Unii wszystkich dziedzinach wszystkich potomków elementu. To także powód, dla którego np.pobierania w AudienceRatings jest wykonywany jako:

SELECT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, t0.ZSECTION ... FROM ZITEM t0 WHERE t0.Z_ENT = ? 

sposób:

  • Rdzeń danych aktualizuje dużo więcej niż 50 wierszy;
  • jeśli chcesz tego uniknąć, musisz unikać dziedziczenia;
  • można uniknąć relacji "jest" z relacjami "ma", ale dwukierunkowa natura danych podstawowych często sprawia, że ​​jest to problem (jeśli 30 obiektów ma połączenie z elementem, to element musi mieć 30 połączeń z innymi obiektami) ;
  • Jeśli pozycja jest po prostu czymś trywialnym, takim jak jednolity znacznik czasu, zwykle łatwiej jest dodać właściwość znacznika czasowego do każdej jednostki i każdy z nich wywołuje wspólny kod do jej ustalenia.
+0

Witam, Tak, mam jednostkę nadrzędną z wieloma dziećmi (http://cl.ly/image/3T3Z1N0M2v18), ale ta jednostka nie została zmodyfikowana. Właśnie zmieniłem nazwę 2 pól tabeli Łącza, ale te pola nie zostały zmapowane ze starego do nowego modelu (więc nie muszę ponownie wstawiać żadnych danych!). Baza danych powinna pozostać taka, jaka jest, ponieważ zmienione nazwy należą do pustej tabeli. – aneuryzm

+0

W bazach SQL przechowywania danych, jeśli 'A' i' B' pochodzą od 'X', to istnieje jedna tabela o nazwie' X', w której przechowywane są instancje zarówno 'A' jak i' B'. Jeśli więc zaktualizujesz encję "B", to Core Data musi ponownie przetworzyć wszystkie instancje zarówno "A", jak i "B", ponieważ musi zaktualizować tabelę "X". W twoim przypadku podejrzewam, że liczba instancji, które mają zostać zaktualizowane, okazuje się znacząca. – Tommy

+0

To jest poprawna odpowiedź. Możesz myśleć, że stół jest pusty, ale tak nie jest. Tam jest właściwie tylko 1 stół zawierający wszystko (z powodu dziedziczenia twego bytu). – Wain

3

Rdzeń danych na iOS wykorzystuje SQLite do przechowywania danych. SQLite nie obsługuje ALTER COLUMN, więc Rdzeń danych działa wokół tego ograniczenia przez:

  1. zmiana nazwy starą tabelę
  2. tworząc nową tabelę ze zaktualizowanymi kolumn
  3. Wkładanie rekordy do nowej tabeli
  4. upuszczenie starego stołu:

Istnieje dobra odpowiedź WR here, która opisuje to nieco bardziej szczegółowo.

Nigdy nie widziałem żadnych problemów z utratą danych przez Core Data podczas wykonywania tej operacji - zakładam, że Apple wdrożyło zabezpieczenia, aby temu zapobiec, ale prawdopodobnie warto skontaktować się bezpośrednio z Apple DTS, aby to potwierdzić.

+0

Jednak nie odwzorowuję pól o zmienionej nazwie, więc nie należy ponownie wstawiać żadnego pola. – aneuryzm

+0

2 zmienione nazwy pól należą do pustej tabeli. – aneuryzm

Powiązane problemy