我有一个Core Data模型代表iOS 4+上的电视指南,有3个类:
Channel
(BBC 1)Program
(Top Gear)Broadcast
(周一晚上8点BBC 1的Top Gear)我有大约40个频道,8000个节目和6000个广播,我想微调导入过程,这样就不需要花一分钟的时间来运行。
导入频道和节目非常简单,因为它们是独立的对象。然而,广播与频道和节目(1对多)有关系,并且频道和节目都与广播(多对1)具有反向关系。为了加快速度,我有一个故障通道的内存字典和只预取了Web服务标识符的程序:我创建一个广播并查看两个字典,以获得相应的通道和程序,而无需往返数据库。
但是当我将节目或频道分配给广播时,频道和节目的反向关系访问会立即触发两个对象的故障,导致大幅减速(6000 * 2请求)和随之而来的内存压力,如核心数据故障仪器报告。我尝试在两个频道和节目上预先获取broadcasts
关系,但这种关系仍然存在问题。
你知道为什么反向关系被访问并且他们的父母有错吗?保存关系时如何避免从数据库中读取?
更新:示例代码,Broadcast
实例的分配/更新方法。 dictionary
变量来自Web服务,channels
和programs
包含由Web服务标识符索引的故障通道和程序对象。错误发生在self.program = program
和self.channel = channel
行。
- (BOOL)assignWithDictionary:(NSDictionary *)dictionary channels:(NSDictionary *)channels programs:(NSDictionary *)programs {
// Add channel relationship
NSNumber *channelIdentifier = [dictionary objectForKey:@"channel_id"];
if (self.channel == nil || ![self.channel.identifier isEqualToNumber:channelIdentifier]) {
Channel *channel = [channels objectForKey:channelIdentifier];
if (channel == nil) {
NSLog(@"Broadcast %@ has invalid channel: %@", identifier, channelIdentifier);
return NO;
}
self.channel = channel;
}
// Same to add a program relationship
// ...
}
我获取频道或节目列表的获取请求:
- (NSDictionary *)itemsForEntity:(NSEntityDescription *)entity {
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSError *error = nil;
NSArray *itemsArray = nil;
request.entity = entity;
request.relationshipKeyPathsForPrefetching = [NSArray arrayWithObject:@"broadcasts", nil];
request.propertiesToFetch = [NSArray arrayWithObjects:@"identifier", @"version", nil];
itemsArray = [self.context executeFetchRequest:request error:&error];
NSAssert1(error == nil, @"Could not fetch the items from the database: %@", error);
{
NSMutableDictionary *items = [NSMutableDictionary dictionaryWithCapacity:itemsArray.count];
for (NSManagedObject *item in itemsArray) {
[items setObject:item forKey:[item valueForKey:@"identifier"]];
}
return [NSDictionary dictionaryWithDictionary:items];
}
}
答案 0 :(得分:1)
不完全确定你在这里要做什么,但......
首先,您不能仅使用故障来改变属性。错误只是占位符,允许您测量/计算对象图和步行关系。如果您实际改变了关系,它将触发故障导致相关对象加载。
如果您尝试仅使用故障在特定Channel
,Program
和Broadcast
对象之间设置关系,那将无效。
我的itemsForEntity:
方法我不明白。它将获取传递的实体的每个现有托管对象,然后它将在字典中返回这些对象。这将导致巨大的内存开销,特别是在Program
对象的情况下,其中有8,000个。
除非您将fetch返回到字典,否则不能使用propertiesToFetch
。如果需要设置关系,则无论如何都不能使用字典返回类型。当你想要的只是某些属性中保存的数据时,你可以同时使用它们。它不是用于操纵对象图的关系的工具。
如果您知道自己将访问现有关系,那么设置relationshipKeyPathsForPrefetching
只会加快速度。当您首先设置关系时,它没有帮助,例如如果broadcasts
关系中没有现有对象,或者您正在添加或删除Broadcast
个对象,则预取broadcasts
密钥路径对您无效。
我不确定我是否理解你的数据模型,但我认为你的方法是错误的。在我看来,您试图在SQL数据库中使用identifier
像主键,这会适得其反。在Core Data中,关系链接到对象,而不是共享属性和值。
通常,如果您有两个或多个具有相同属性名称且具有相同值的对象,则在大多数情况下您的数据模型设计不佳。