Einfach holen mit. @ Count Prädikat eine lange Zeit (~ 30 Sekunden)
-
22-09-2019 - |
Frage
Ich habe 2 Einheiten, A und B, die eine viel zu viele Beziehung haben.
Die A Unternehmen hat über 10.000 Objekte in und B hat etwa 20 Objekte.
Grundsätzlich können Objekte zu einem oder mehrere B-Objekten in Beziehung gesetzt werden, und die B-Objekte zu verfolgen, welche A-Objekte mit denen sie verbunden sind. Dies wird mit der inversen Beziehung Einstellung gemacht.
Ich möchte nur all B-Objekt zurückzugeben, die nicht zu einem A-Objekt verknüpft ist. Die Abruf- ich verwende, ist dies:
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
[fetch setIncludesPropertyValues:NO];
[fetch setEntity:[NSEntityDescription entityForName:@"B" inManagedObjectContext:context]];
[fetch setPredicate:[NSPredicate predicateWithFormat:@"aObjects.@count == 0"]];
return [context executeFetchRequest:fetch error:nil];
Es ist jedoch das Abruf Ausführung eine sehr lange Zeit in Anspruch nimmt, ca. 30 Sekunden. Ich verstehe das nicht, denn obwohl es eine große Anzahl von A-Objekten ist, diese holen nichts mit ihnen zu tun hat, und muss nur die 20 B-Objekte überprüfen.
Wenn ich das Prädikat Kommentar aus, so dass die Rendite Objekte alle B holen, dann holen die wirklich schnell ist, wie sie nur das Abrufen 20 Objekte erwarten würde. So scheint es, dass das Prädikat einig A beteiligt ist immer Objekte und verursacht es eine lange Zeit in Anspruch nehmen!
Schuppen Kann jemand irgendein Licht auf, warum das so lange dauert?
Edit:
Ich habe SQL Debug-Informationen bekommen und hier ist, was Ausgang ist:
CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK FROM ZTABLEVIEWOBJECT t0 WHERE ((SELECT COUNT(*) FROM ZTABLEVIEWOBJECT t1 JOIN Z_10BOBJECTS t2 ON t1.Z_PK = t2.Z_10AOBJECTS3 JOIN ZTABLEVIEWOBJECT t3 ON t2.Z_12BOBJECTS = t3.Z_PK WHERE (t0.Z_PK = t2.Z_12BOBJECTS) ) = ? AND t0.Z_ENT = ?)
CoreData: annotation: sql connection fetch time: 49.4198s
CoreData: annotation: total fetch execution time: 49.4240s for 0 rows.
I sollte hinzufügen, dass beide Einheit A und Einheit B, vererben (einen Elternteil haben) eine gemeinsame TableViewObject Einheit, die gemeinsamen Werte zwischen dem beide (Sektionsnamen und Sortiernamen usw. wie Tabellenansicht) hält. Hoffe, das hilft!
Lösung
Wenn ich Sie richtig bin zu verstehen, haben Sie eine viele-zu-viele-Beziehung zwischen diesen Objekten und die das Problem verursachen können. In einer many-to-many gibt es eine Join-Tabelle zwischen B und A und der Join-Tabelle wahrscheinlich hart getroffen wird immer. Ich würde sehr gespannt sein, die SQL, um zu sehen, die mit Ihrem holen erzeugt wird.
UPDATE
Versuchen Sie Ihr Prädikat ändern „aObjects == null“ zu sein und sehen, was passiert. Da es sich um eine many-to-many-Beziehung, die die einzige andere Prädikat ist, dass ich daran denken kann, Macht geben Sie die Ergebnisse, die Sie suchen.
Andere Tipps
Sie ersetzen
aObjects.@count == 0
mit
ANY aObjects == nil
Es wird drastisch die Zeit meines query (iPhone OS 3.0) reduzieren. Es funktioniert auch für != nil
(@count != 0
).
Wenn Sie einen SQLite-Speicher verwenden, können Sie auf SQL-Fehlerprotokollierung aktivieren. Core Data protokolliert alle SQL-Befehle es an die Konsole zu machen. Ich habe dies sehr nützlich fand etwas Unerwartetes passiert hinter den Kulissen zu entdecken. Es wird auch Zeitinformationen für jeden SQL-Befehl auszudrucken!
Um dies zu tun, doppelklicken Sie auf die ausführbare Datei in Ihrem Projekt, gehen Sie auf die Argumente Registerkarte und fügen Sie ein Argument:
-com.apple.CoreData.SQLDebug 1
Ich denke, das ist ein wenig spät, aber vielleicht dies helfen wird, andere, die in dieses Problem. Die umgekehrte Beziehung auf bObjects
ist ein Attribut von bObjects
und als NSSet
in bObjects
dargestellt. Wenn entweder der NSSet
nil
oder die Anzahl der Objekte in der NSSet
ist gleich Null ist, dann gibt es keine aObjects
auf die jeweilige bObject
bezogen.
Test für die aObjects.@count
erfordert beide Tabellen repräsentieren die Objekte abgefragt werden und einige wirklich hässliche SQL erzeugt. Was Sie versuchen, hier muss nicht weiter dann die bObject
.