如何加快核心数据迁移或其他解决方案
Posted
技术标签:
【中文标题】如何加快核心数据迁移或其他解决方案【英文标题】:How to speed up CoreData Migration or another solutions 【发布时间】:2014-02-24 13:45:17 【问题描述】:我将 Coredata 用于我的 ios 应用程序。它有大约 20 个表,我的应用程序使用数据库中的可能图像(图像编辑应用程序)。所以数据库数据如此庞大和沉重。
有一天,我在一张表中添加了几列。它只是字符串列。当然我知道如何迁移和实现它,所以我添加了新的 .xcdatamodel 并更改了当前的。当我在我的设备中测试时,我没有收到任何错误和冲突。所以我将它发布到iOS开发者中心,它可以被宣布。终于,很多用户开始更新我的应用了。
但有些用户说“从未完成更新”。 “更新需要 50 分钟。”等等... 更新意味着迁移。我通过用户报告的进度确认了这一点。我不敢相信迁移需要 50 分钟!但也许这是真的。因为当我测试使用 50 张图像并保存到 CoreData 时,我的设备大约需要 1 分钟。我认为我们的客户使用 300 ~ 500 张图像和用户其他数据。如果是 iPhone4 或 iPhone4S,迁移需要很长时间...
所以我想知道如何为这些用户加快 CoreData 迁移。 现在我使用的是自动迁移,否则我可以选择手动迁移。 我发现了一些技巧并告诉工程师,并收集它,我推断手动迁移比自动迁移慢。 我正在寻找其他并行解决方案。它将核心数据导出到 PC。并且 PC 迁移而不是 iPhone。 iPhone 会导入迁移的数据。有谁知道这种方式可行吗?
最后,我放上我的迁移代码。这真的很简单。
@try
// init application (Before application:didFinishLaunchingWithOptions:)
LOG(@"start migration");
NSPersistentStoreCoordinator *migPersistent;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:[[self class] sqliteFileInDocumentsUrlString]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
NSError *error = nil;
migPersistent = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![migPersistent addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
[migPersistent release];
return NO;
[migPersistent release];
LOG(@"finish migration");
@catch (NSException *exception)
.....
@finally
// Do Nothing
此外,此代码在 MainThread 上运行。 喜欢 ViewDidAppear(LoadingWindow) -> performSelector:withObject:afterDelay -> 迁移。
感谢您观看此问题,对不起,我的英语很糟糕..
编辑于 2014.02.25 21:11 我得到了跟踪文件并上传了以下 URL。https://www.dropbox.com/sh/dmlf4j4z3vkj3p0/DrDBL_guYy [测试流程](设备:iPodtouch 5th Gen iOS 7.0.6) 1. 在之前的版本中插入了 195KB(Width:960,Height:1280) x 1000 图片。 2. 安装当前版本并运行迁移。它完成了大约11分钟。 那么为什么用户得到 50 分钟???
编辑于 2014.02.26 8:59
抱歉,以上网址有误。请检查此网址。https://www.dropbox.com/s/8xaxwyfex7gyjdt/traceFolder.zip
编辑于 2014.02.26 10:43
-[PapeDataManager 迁移] 中发生了什么?如果可以,请添加代码
上面的代码。这个方法得到了 184977x。
[migPersistent addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
options:options error:&error]
-[PapeDataManager repairImageNamePath] 中发生了什么?
这个方法得到了 160775x。[self.managedObjectContext save:&error]
self.managedObjectContext 是 NSManagedObjectContext。 保存似乎是一个繁重的过程。因为它是在迁移之后。
现在,我有一些问题。
(1) MainThread 的运行时间总结约为 6 分钟,而 TimeProfiler 上的进程总时间为 11 分钟。为什么会出现这种差异?
(2) 当我在迁移时按下主页按钮时,迁移过程会死机吗?我只是在检查它。但如果你知道这一点。请告诉我。
编辑于 2014.02.26 12:09
关于 (2)。 我已经测试了 50 个图像迁移。 当我按下主页按钮和 30 秒后,后台任务已暂停。
所以像这样的流程 应用程序午餐->加载开始->迁移->(按下HomeButton并将应用程序发送到后台)->迁移完成->后台进程暂停->(推送应用程序图标并将应用程序发送到前台)->保存->加载完成
我不知道为什么应用程序在后台时加载过程不会继续。也许我们的用户对加载时间长感到愤怒的原因就是这个。
【问题讨论】:
我知道这个问题,但没有完整的解决方案。需要这么长时间的原因是整个数据库被读入内存进行迁移。有手动迁移的可能性,您可以在其中微调迁移。请参阅 developer.apple.com/library/mac/documentation/cocoa/conceptual/… 标题为多次传递—处理大型数据集的部分 我建议将代码移到主线程之外,并允许用户在迁移过程中使用应用程序。 也许你应该把图像放在核心数据之外? @Volker 这是不正确的。发生自动/轻量级迁移时,不会将整个数据库加载到内存中。这只发生在大量迁移时。 @Volker 如果您使用的是映射模型,那么您正在进行大量迁移。 【参考方案1】:即使对于自动/轻量级迁移而言,持久存储中的图像似乎花费的时间比正常情况要长得多。
假设您现在已经建立了一个包含 500 张图像的测试用例来跟踪它;下一步是在迁移过程中针对应用程序运行工具,并查看时间花在了哪里。如果时间确实在 Core Data 中(而不是一些 UI 事件正在发生),那么请使用 Instruments 的跟踪编辑您的帖子。
您的应用程序很可能会在迁移后立即尝试对数据执行某些操作,这会消耗时间。没有仪器痕迹很难分辨。
更新(来自跟踪)
-[PapeDataManager migrate]
发生了什么?如果可以,请添加代码
-[PapeDataManager repairImageNamePath]
发生了什么?
-repairImageNamePath
花费的时间最多,如果你能解决这个问题,你会看到性能显着提升。
更新 2
打开SQLite debug 可以让您看到在这段时间内发生了什么。如果由于存储中的 blob 确实是大量的 sql 调用,那么您将需要重构存储,可能进行手动迁移(不是繁重,但从 Core Data 导出并重建文件)来解决此问题。
【讨论】:
感谢您的建议。我应该在仪器中使用哪个库?一些库有.. Time Profiler, Activity Monitor, 等等。 从时间探查器开始。观看有关它的 WWDC 视频。 该跟踪中没有数据。 对不起,我弄错了。请检查新网址。以上是关于如何加快核心数据迁移或其他解决方案的主要内容,如果未能解决你的问题,请参考以下文章