问题描述
我有一个相当大的基于核心数据的数据库模式(〜20个实体,超过140个属性),它正在经历巨大的变化,因为它从1.x代码库迁移到我们的2.x代码库。
我非常熟悉执行轻量级迁移,但是我对这个特定的迁移有点失望,因为有一些实体用来存储相关对象作为实体的可变属性但现在我想将它们迁移到实体。
这似乎是一个完美的例子,当你应该使用重型迁移,而不是一个轻量级的,但我不太高兴那么。我不熟悉重迁移,一个实体有这个数组 - >建模的关系转换发生占据了大约90%的数据库中的行,这些数据库的大小通常超过200 MB,我知道我们很大一部分客户使用iPad 1。结合苹果文档和Marcus Zarra(优秀的)Core Data书中关于重迁移的速度和内存使用的重复警告,我非常谨慎,并寻找另一种方式来处理这种情况。
WWDC 2010的掌握核心数据会话118(,需要登录,第9到最后一张幻灯片,标题为迁移后处理是我所指的)提到一种排序工作的方式 - 执行迁移,然后使用存储元数据以标记您要执行的自定义后处理是否已完成。我认为这可能是去的方式,但它觉得有点hacky(因为缺乏一个更好的话)给我。此外,我担心留下属性挂在实际中,已弃用。例如。如果我将实体foo的barArray属性移动到实体foo和实体bar之间的关系,而且我没有barArray,barArray仍然存在作为可以写入和读取的属性。解决这个问题的一个潜在方法是通过改变它们的名称来废弃这些属性,以及可能重写访问器来断言它们是否被使用,但是使用KVO,则不能保证编译 - 时间解决方案,将阻止人们使用它们,我不喜欢留下陷阱代码,特别是因为所述'陷阱代码'将需要在只要我有潜在客户仍需要从1.0迁移。
这变成了比我想象的更多的大脑转储,所以为了清楚起见,我的问题是:
1)是一个沉重的迁移一个特别差的选择与我工作的约束? (业务关键型应用程序,缺乏重迁移经验,数据库超过200 MB,数万行,客户使用运行iOS 5+的iPad 1)
2)如果是,迁移后处理技术在会话118中描述我最好的赌注?
3)如果是这样,我如何立即/最终消除那些弃用的属性,使他们不再污染我的代码基础?
我的建议是远离重度迁移;全停。它在iOS上太贵了,很可能会导致不可接受的用户体验。
在这种情况下,我会做一个延迟迁移。创建一个具有关联对象的轻量级迁移。
然后进行迁移,但不要移动任何数据。 b
$ b
更改该新关系的访问器,以便它首先检查旧的可变换对象,如果可变换对象被填充,则拉出数据,将其复制到新关系,然后nil退出可变换对象。
这样做会导致数据在使用时移动。
如果你想对这些新对象使用谓词,那么它会是...混乱。你会想做一个双程获取。 使用未命中该新对象的谓词进行抓取,然后在它们是内存之后执行部分抓取,以便移动可转换对象。
I have a rather large Core Data-based database schema (~20 entities, over 140 properties) that is undergoing large changes as it migrates from our 1.x code base over to our 2.x code base.
I'm very familiar with performing lightweight migrations, but I'm a bit flummoxed with this particular migration because there's a few entities that used to store related objects as transformable attributes on the entity itself, but now I want to migrate those to actual entities.
This seems like a perfect example of when you should use a heavy migration instead of a lightweight one, but I'm not too happy about that either. I'm not familiar with heavy migrations, one of the entities that has this array -> modeled relationship conversion occurring takes up ~90% of the rows in the database, these databases tend to be more than 200 MB in size, and I know a good portion of our customers are using iPad 1s. That combined with the repeated warnings in Apple documentation and Marcus Zarra's (excellent) Core Data book regarding the speed and memory usage of a heavy migration make me very wary, and searching for another way to handle this situation.
WWDC 2010's "Mastering Core Data" session 118 (slides here, requires login, the 9th to last slide, with the title 'Migration Post-Processing' is what I'm referring to) mentions a way to sort of work around this – performing the migration, then using the store metadata to flag whether or not custom post processing you want to perform has been completed. I'm thinking this might be the way to go, but it feels a bit hacky (for lack of a better word) to me. Also, I'm worried about leaving attributes hanging around that are in practice, deprecated. ex. if I move entity foo's barArray attribute into a relationship between entity foo, and entity bar, and I nil out barArray, barArray still exists as an attribute that can be written to and read from. A potential way to solve this would be to signal that these attributes are deprecated by changing their names to have "deprecated" in front, as well as perhaps overriding the accessors to assert if they're used, but with KVO, there's no guaranteed compile-time solution that will prevent people from using them, and I loathe leaving 'trap code' around, especially since said 'trap code' will have to be around as long as I potentially have customers who still need to migrate from 1.0.
This turned into more of a brain dump than I intended, so for sake of clarity, my questions are:
1) Is a heavy migration a particularly poor choice with the constraints I'm working under? (business-critical app, lack of experience with heavy migrations, databases over 200 MB in size, tens of thousands of rows, customers using iPad 1s running iOS 5+)
2) If so, is the migration post-processing technique described in session 118 my best bet?
3) If so, how can I right away/eventually eliminate those 'deprecated' attributes so that they are no longer polluting my code base?
My suggestion is to stay away from heavy migration; full stop. It is too expensive on iOS and most likely will lead to a unacceptable user experience.
In this situation I would do a lazy migration. Create a lightweight migration that has the associated objects.
Then do the migration but don't move any data yet.
Change the accessor for that new relationship so that it first checks the old transformable, if the transformable is populated it pulls the data out, copies it over to the new relationship and then nil's out the transformable.
Doing this will cause the data to move over as it is being used.
Now there are some issues with this design.
If you are wanting to use predicates against those new objects it is going to be ... messy. You will want to do a two pass fetch. i.e. Fetch with a predicate that does not hit that new object and then do a section fetch once they are memory so that the transformable gets moved over.
这篇关于核心数据迁移技术:移动属性 - >建模关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!