8

我创建了一个新模型并重命名了一个实体的 2 个字段。该实体在之前的应用版本中从未使用过,因此我没有将其映射到数据库中新更新的实体。因此映射没有映射任何新的东西,但是迁移非常慢(主表中大约 50 行需要 3 秒)。我想知道核心数据是否正在创建一个新数据库并删除旧数据库,然后重新插入所有数据。这是迁移日志文件:http ://cl.ly/3H1v252R1p1c

附言。如果NSInferMappingModelAutomaticallyOption是,这是否意味着我可能会遇到数据丢失,因为映射是由核心数据即兴创作的?

谢谢

4

2 回答 2

3

iOS 上的 Core Data 使用 SQLite 进行数据存储。SQLite 不支持ALTER COLUMN,因此 Core Data 通过以下方式解决此限制:

  1. 重命名旧表
  2. 使用更新的列创建一个新表
  3. 将记录插入新表
  4. 丢掉旧桌子

这里有一个很好的 SO 答案,它更详细地描述了这一点。

我从未见过 Core Data 在执行此操作时丢失数据的任何问题——我认为 Apple 已经实施了保护措施来防止这种情况发生,但可能值得直接与 Apple DTS 联系以确认。

于 2013-06-23T22:59:23.613 回答
3

你能告诉我们你的数据库模式吗?我的猜测是您在其中大量使用了对象继承。

Core Data 通过为父实体创建单个表并为子实体使用的所有字段的联合添加列来实现 SQL 存储中的继承。因此,您可能认为您只重命名了一个实体上的两个字段,但 Core Data 必须将更改应用于从该实体继承或具有该实体的共同祖先的每个对象。

在您的特定架构中,您似乎有一个实体 Item,其中至少有 Genre、AudioTrack、Studio、Director、Store、Movie、Condition、Region、Owner、AspectRatio、Year、MyRating、Episode、Edition、Format、Producer、 Writer、AudienceRating、SeenIt 和 Movie 下降。当我通过眼睛阅读您的日志而不是自动分析它时,可能还有其他人。因此,Core Data 创建了一个名为 Item 的表,其中存储了每个实体的每个实例。每当这些实体中的任何一个(或我可能没有找到的其他实体)发生变化时,Core Data 都必须更新每个实体的所有实例的记录。

这就是为什么你会看到:

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 ) 

那是包含 Item 的所有后代的所有字段的并集的表。这也是为什么例如对 AudienceRatings 的提取被执行为:

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

所以:

  • Core Data 正在更新超过 50 行;
  • 如果你想避免这种情况,你需要避免继承;
  • 你可以避免 'is a' 关系和 'has a' 关系,但 Core Data 的双向性质常常使这很痛苦(如果 30 个对象与 Item 有连接,那么 Item 必须与其他对象有 30 个连接);
  • 如果 Item 只是像统一时间戳这样微不足道的东西,通常只需将时间戳属性添加到每个实体并让每个实体调用一段通用代码来建立它,通常会更容易。
于 2013-06-23T23:33:22.703 回答