2011-08-12 6 views
6

Tengo un modelo de datos básicos que representan una guía de TV en iOS 4, con 3 clases:Rendimiento: relaciones Core Obtener datos falla después de haber sido asignado

  • Channel (BBC 1)
  • Program (Top Gear)
  • Broadcast (Top Gear de la BBC 1 el lunes a las 20:00)

tengo cerca de 40 canales, programas 8000 y 6000 las emisiones, y me gustaría afinar el im proceso de puerto para que no demore un minuto en ejecutarse.

La importación de canales y programas es fácil porque estos son objetos independientes. Sin embargo, una transmisión tiene una relación con un canal y con un programa (de 1 a varios), y ambos canales y programas tienen relaciones inversas con las emisiones (de muchos a 1). Para acelerar las cosas, tengo un diccionario en memoria de canales de fallas y programas que solo obtuvieron previamente su identificador de servicio web: creo una transmisión y busco en los dos diccionarios para obtener el canal y el programa correspondientes sin un viaje de ida y vuelta a la base de datos.

Pero cuando asigno un programa o canal a una transmisión, el acceso de relaciones inversas del canal y del programa desencadenan inmediatamente un error de ambos objetos, causando una desaceleración masiva (6000 * 2 solicitudes) y la consiguiente presión de memoria como se muestra en el informe de los fallos de datos básicos. Intenté precargar la relación broadcasts tanto en canales como en programas, pero la relación aún tiene errores.

¿Tiene alguna idea de por qué se accede a las relaciones inversas y culpan a sus padres? ¿Cómo evito leer en la base de datos cuando guardo una relación?

ACTUALIZACIÓN: Código de ejemplo, mi método de asignación/actualización para una instancia de Broadcast. La variable dictionary proviene del servicio web y channels y programs contienen los canales de falla y objetos de programas indexados por el identificador del servicio web. La falla ocurre en las líneas self.program = program y 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 
    // ... 
} 

y mi petición de recuperación para obtener los canales o programas de la lista:

- (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]; 
    } 
} 
+1

+1, porque una vez tuve un problema muy similar que no pude resolver, finalmente haciendo cosas completamente diferentes. Sin embargo, aún tengo curiosidad sobre lo que pude haber hecho al respecto. – Toastor

+0

¿Cómo es su "programa o canal de difusión" usando solo un "identificador"? Supongo que el "identificador" es un managedObjectID o un URI de la misma? Sugeriría mostrar el código donde haces esto. – TechZen

+0

Obtengo datos de un servicio web que describe las relaciones usando identificadores numéricos, nada que ver con los identificadores de datos centrales (debería haberlo mencionado) – ndfred

Respuesta

1
No

exactamente seguro de lo que está tratando de hacer aquí, pero ...

El primero es que no puedes alterar propiedades usando solo fallas. Las fallas son solo marcadores de posición que le permiten medir/contar el gráfico del objeto y las relaciones de andar. Si realmente altera una relación, disparará la falla que causa la carga de los objetos relacionados.

Si está tratando de establecer relaciones entre objetos específicos Channel, Program y Broadcast usando solo fallas, eso no funcionará.

Su método itemsForEntity: No entiendo. Traerá todos los objetos administrados existentes de la entidad pasada y luego devolverá esos objetos en un diccionario. Eso causará una sobrecarga de memoria masiva especialmente en el caso de los objetos Program de los cuales hay 8,000.

No puede usar propertiesToFetch a menos que configure la búsqueda para regresar al diccionario, que no es así.No puede usar un tipo de devolución de diccionario de todos modos si necesita establecer relaciones. Utiliza ambos cuando lo único que desea es que los datos estén en ciertos atributos. No es una herramienta para manipular las relaciones del gráfico del objeto.

Configurar el relationshipKeyPathsForPrefetching solo acelera las cosas si sabe que va a acceder a una relación existente. No ayuda cuando establece las relaciones en primer lugar, p. si no hay objetos existentes en las relaciones broadcasts o está agregando o eliminando objetos Broadcast, la recuperación previa del keypath broadcasts no hace nada por usted.

No estoy seguro de entender su modelo de datos lo suficientemente bien, pero creo que va por el camino equivocado. Me parece que está tratando de usar el identifier como una clave principal en una base de datos SQL y eso es contraproducente. En Core Data, una relación se vincula a objetos juntos, no un atributo y valor compartido.

Como regla general, si tiene dos o más objetos con el mismo nombre de atributo con el mismo valor, entonces, en la mayoría de los casos, tiene un modelo de datos mal diseñado.

+0

Gracias por su aporte. A partir de iOS 4, los objetos de repuesto se pueden instanciar con un 'propertiesToFetch' en lugar de solo diccionarios. Supongo que, dada la forma en que funciona Core Data, el objeto tendrá que tener una falla para actualizar sus relaciones. Trataré de trabajar exclusivamente con ID de objeto para confirmarlo. El identificador es externo, tengo que mantenerlo sincronizado con el servicio web para manejar las actualizaciones y tengo que usarlo además de una identificación de objeto que Core Data me impone. – ndfred

+0

Revisaré los cambios en propertiesToFetch, a veces echo de menos los cambios debido a que no tengo que verificar tanto los documentos. No hay problema con el almacenamiento de un ID para un DB externo, pero como regla, solo necesita almacenar el valor en una entidad. A continuación, relaciona todas las demás entidades que necesitan saber sobre el ID con esa entidad única. No utiliza el mismo valor de atributo para relacionar objetos. – TechZen

Cuestiones relacionadas