Pregunta

Tengo cierta ineficiencia en mi aplicación que me gustaría entender y corregir.

Mi algoritmo es:

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object

Me estoy haciendo la comprobación de las líneas A y B mediante la creación de una consulta predicado con la clave del objeto relevante que es parte de mi esquema. Veo que tanto A (siempre) y B (si la ejecución ramificado en esa parte) generan un SQL seleccionar como:

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.

0.0071s para una consulta está bien en un dispositivo 3G, pero si se agrega 100 de éstos para arriba, que acaba de recibir un bloqueador de 700ms.

En mi código, estoy usando un ayudante para hacer estas recuperaciones:

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}

Siento que esto es un error y que debería hacer la comprobación de alguna otra manera. Sólo se debe golpear la base de datos de una vez debe provenir de la memoria a partir de entonces, ¿verdad? (El SQL es ejecutado incluso para objetos, que yo sepa a ciencia cierta existen a nivel local y debería haber sido cargados en la memoria con las consultas previas.) Sin embargo, si sólo he myObjectId de una fuente externa, esto es lo mejor que podía pensar.

Por lo tanto, tal vez la pregunta es: si tengo myObjectId (Int64 una propiedad de Datos Básicos en MiObjeto), ¿cómo debo correctamente comprobar si existe el objeto local relevante en la tienda de CD o no? Precargar el conjunto de posibles coincidencias y luego predicado un array local?

(Una posible solución se está moviendo a un subproceso de fondo Esto estaría bien, excepto que cuando llegue a los cambios de la rosca y hago [mergeChangesFromContextDidSaveNotification moc: aNotification];. (Siendo objetos de subproceso de fondo cambió a modo de notificación ), esto todavía bloques.)

¿Fue útil?

Solución

Leer "Implementación de Find-o-Crear de manera eficiente" en la Guía de Programación de Datos Básicos.

Básicamente lo que necesita para crear una matriz de ID o propiedades como nombres, o cualquier cosa que se tiene de la entidad objeto administrado.

A continuación, es necesario crear un predicado que filtrará los objetos gestionados mediante esta matriz.

[fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(objectID IN %@)", objectIDs]];

Por supuesto "ObjectID" podría ser cualquier cosa que se puede utilizar para identificar. No tiene por qué ser el NSManagedObjectID.

A continuación, se podría hacer una petición de recuperación, e iterar los objetos inverosímiles resultantes, para encontrar duplicados. Añadir una nueva si no existe.

Otros consejos

Probablemente se podría tomar una lección de clientes de correo electrónico.

Trabajan mediante la consulta primero al servidor para obtener una lista de los ID de mensaje. Una vez que el cliente tiene esa lista, a continuación, se compara contra su almacén de datos local para ver si algo es diferente.

Si hay una diferencia que se necesita uno de un par de acciones. 1. Si existe en el cliente, pero no del servidor y que son IMAP, a continuación, eliminar localmente. 2. Si existe en el servidor, pero no el cliente, a continuación, descargar el resto del mensaje.

En su caso, la primera consulta para todos los identificadores. A continuación, enviar una consulta de seguimiento para agarrar todos los datos para los que no tiene ya.

Si usted tiene una situación en la que podría existir localmente el disco, pero podría haber sido actualizado desde la última descarga en el servidor, a continuación, la consulta debe incluir la última fecha de actualización.

Usted debe hacer FETCH en todos los objetos, pero sólo buscar el ID de servidor para los objetos.

Con setPropertiesToFetch: con setResultType:. establece en NSDictionaryResultType

Parece que lo que necesita es un NSSet de NSManagedObjectIDs que se carga en la memoria o almacenado en algún lugar se accede más rápidamente que su almacén de objetos persistentes.

De esta manera se puede comparar identificadores de objetos de la red con los ID de objeto de la caché sin tener que realizar una consulta a un gran conjunto de recuperación de datos.

añadir Tal vez el ID de la caché desde dentro -awakeFromInsert dentro de sus clases de entidades gestionadas?

Después de luchar con este mismo tema durante años, finalmente me encontré con este blog, que resuelve totalmente (y es un bloque de código reutilizable como premio!).

http://henrik.nyh.se/2007/01/importing-legacy-data-into-core-data-with-the-find-or-create-or-delete-pattern

Si bien el ejemplo de código no cubre la parte de red; sólo hay que cargarlo en un NSDictionary. y luego esta se ocupa de la sincronización del contexto local de Datos Básicos.

No es una respuesta, pero una URL actualizada de la documentación "Importación de datos de manera eficiente"

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW1

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top