Core Data und seine Grenzen

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Core Data und seine Grenzen

      Guten Morgen liebe Gemeinde,

      ich bin gerade dabei, ein Projekt zu planen und benötige dafür eine Datenbank.
      Ich bin mir nicht ganz sicher, ob ich CD oder SQLite verwenden soll.
      Im ersten Schritt soll es eine App für Mac OS X werden.

      Zu den Anforderungen:
      - die DB wird ca. 15 Tabellen beinhalten;
      - davon werden ca. 8 Relations zueinander haben (1:1, 1:n und m:n);
      - jede Tabelle wird >5 Attribute besitzen;
      - zu erwarten sind nach ca. einem halben Jahr Betrieb 50.000 Datensätze (Datensätze aller Tabellen addiert);
      - spätere Portierung auf iOS (mit iCloud Sync)

      Wo liegen die Grenzen von Core Data?
      Die Implementierung von CD in einer App ist ja allerliebst und spart eine Menge Aufwand.
      Allerdings ist SQLite eine "echte" Datenbank und kann die Anforderungen mit Sicherheit erfüllen.
      Ich würde CD bevorzugen, aber was meint ihr?

      Vielen Dank im Voraus und
      ich wünsche einen angenehmen Mittwoch :)
    • CoreData ist keine Datenbank....

      Wenn du CoreData benutzen willst must du dich von deinem Datenbank Denken verabschieden und neu denken. Wenn Du iCloud machen willst ist CoreData das einzige was wirklich funktioniert. Es sei denn Apple hat mitlerweile eine brauchbare SQlite Unterstützung eingebaut.

      Gruß

      Claus
      2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

      Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
    • Naja, du hast ein SQLite, in dem dein Core Data Objektgraph abgelegt wird. Insofern nimm doch einfach beides. :-P

      - kommt ungefähr hin, es werden nur soweit ich mich erinnere zusätzlich fünf Meta-Tabellen angelegt. 'Tabellen' ist übrigens das falsche Wort für die Arbeit mit Core Data. Nutze lieber 'Objekte' oder 'Entitäten'.

      - warum hast du Entitäten ohne Relations? Und dann auch noch die Hälfte der Entitäten? Das riecht nach einem Designfehler. Vor Allem in Verbindung mit CoreData. Faulting funktioniert wunderbar, wenn du deine Top-Level Objekte aus der Datenbank lädst und dann im Speicher mit eben diesen Objekten arbeitest. Finger weg von zu vielen Fetch Requests, sag ich immer. Wenn du mit Core Data arbeiten möchtest empfehle ich dir so wenig Top-Level-Tabellen wie möglich. Also möglichst wenig 'starke Entitäten' und möglichst viele 'schwache Entitäten'. Ansonsten wird das eine datenbankähnliche Abfrageorgie, deren Performance dich nicht sehr begeistern wird. ;)

      - ist der Entität egal. Bei > 5.000 hätte ich mir Sorgen gemacht und einen Designfehler gewittert.

      - interessant ist da die Frage der Anzahl der starken Entitäten, also die Anzahl der Objekte, die du initial via Fetch Request in den Speicher lädst. 49.000? Könnte übel werden. Und riecht nach einem Designfehler. 50? Kein Ding.

      - Core Data gibt es von Haus aus auf iOS und iCloud geht gar nicht ohne. Mit geht es angeblich nur schleppend, ohne jedoch gar nicht.

      Wenn du mit Core Data arbeitest tu dir selbst einen Gefallen: lade die Top-Level Objekte via Fetch-Request, pack sie dir in eine Collection und arbeite nur mit dieser weiter. Vergiss das ganze Datenbankgeraffel. Brauchste nicht. Führt nur zu Problemen beim Verständnis. Du arbeitest mit Objekten. Punkt. Aus. Ende.
      «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

      Iä-86! Iä-64! Awavauatsh fthagn!

      kmr schrieb:

      Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
    • Hallo Lucas de Vil,

      auch dir vielen Dank für deine Antwort =)

      Und vielen Dank für deine ausführlichen Infos.
      Zum Glück stecke ich ja "noch" in der Planungsphase und kann deine Tipps berücksichtigen.

      Lucas de Vil schrieb:

      Wenn du mit Core Data arbeitest tu dir selbst einen Gefallen: lade die Top-Level Objekte via Fetch-Request, pack sie dir in eine Collection und arbeite nur mit dieser weiter. Vergiss das ganze Datenbankgeraffel. Brauchste nicht. Führt nur zu Problemen beim Verständnis. Du arbeitest mit Objekten. Punkt. Aus. Ende.
      Das war sowieso meine Absicht - hätte ich vielleicht erwähnen sollen ^^

      Gruß
    • Die Grenzen von Core Data wirst du so nicht erreichen, vor allem nicht mit gutem Code.

      Übrigens ist die Aussage, dass iCloud mit Core Data funktioniert ziemlich gewagt. Nicht einmal Apple würde das sagen. Nein, nicht einmal Apple sagt das. Bloß nicht in der Doku, sondern in Konferenzräumen im Keller (Etage -3, IIRC) Londoner Hotels. Aber mit .9 wird alles besser. So wie mit .8. ;-)
      Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
      25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
    • Das Projekt liegt hier noch ganz warm auf der Festplatte...

      Es ging darum, ein Foto in Quadrate aufzuteilen, die jeweils in der Farbe eingefärbt die das Foto an der Stelle hat. Bei einem Touch auf ein Quadrat teilt sich das wiederum in vier gleiche "Unterquadrate"... . Also quasi ein Klötzchenbild, das durch tippen immer feiner wird bis schließlich das Foto sichtbar ist.

      Das ganze fängt Programmiertechnisch mit einer RootCell an, wird die berührt, teilt sie sich auf und fügt sich selbst wieder vier Cells als Child Objekte hinzu. Für nen Hittest bohrt man sich quasi von oben nach unten durch, und bekommt so schnell seinen Treffer, ohne 3000 Objekte testen zu müssen. Das ganze Ding kann sich dann auf ein CALayer pinseln und gut ist.

      So ein Cell Objekt enthält ein CGRect mit seiner Position und ggf. noch Verweise auf seine vier Kinderchen - sehr überschaubar würde ich mal sagen. Auch ein Graph mit ein paar tausend Objekten, die da schnell entstehen läuft völlig ohne Performanceprobleme.

      Nu muss das Ding auf Platte...

      Am Start war immer der gleiche Graph mit ca. 3500 Objekten

      1. Versuch: NSCoding. Akzeptable Serialisierungs - , Deseialisierungsgeschwindigkeit. Mit ein wenig GrandCentral jedem User zuzumuten. Vielleicht so 2 Sekunden Verzögerung. Plattenbedarf so bei 700kB.

      Ich hab auf nem Rechner nit 4K Hauptspeicher angefangen zu coden, also muss das besser werden

      2. Versuch: Das Ding in nen JSON Schlauch seialisiert. Die 3500 Objekte werden eigentlich ohne das man eine große Verzögerung merkt geladen. Die JSON Wurst war so 200kB groß. Das wurde dann noch im Speicher gezippt, dann waren noch ca. 50kB auf die Platte zu schreiben. Da kann man dem User das speichern und laden eigentlich sogar schon synchron zumuten.

      Aber nur weil der User mal ein Quadrat unterteilt weil er zufällig mal auf das Bild getoucht hat immer alle 3500 Objekte serialisieren, schon Scheiße!

      Gib CoreData mal wieder ne Chance, Manfred. Eigentlich finde ich es geil. Dummerweise bin ich damit bisher in jedem Projekt an die Wand gefahren.

      Die Entity "OverlayCell" enthält 4 Double (den Frame) und und eine Relation, die Childs.

      Beim generieren des "NSObject basieren" testgraphen zuckt der Profiler kaum. Bei der "NSManagedObject basierten" Variante gehst du dir am besten mal nen Kaffee holen. Das iPhone zusätzlich vor nen Ventilator zu stellen um es zu kühlen ist auch nicht verkehrt. Das waren so gut 45 Sekunden (auf die Tausendstel zu schauen hab ich mir erspart).

      Das speichern, wenn sich tatsächlich mal nur ein paar Objekte ändern geht flott, hier spielt CD seinen Vorteil der granulierten Speicherung voll aus. Wenn es aber mal ein paar tausend sind, weil der User eben nicht nur zwei Quadrate aufgeteilt hat, sondern gerade das ganze Bild freitappt - Kaffee und Ventilator bereit stellen, wenn er das auf die Platte rausschreibt.

      Das es mit dem Faulting Verhalten von CD etwas knifflig werden kann, wenn ich den kompletten Graphen lade um ihn dann zu zeichenen habe ich geahnt. Aber das es so grottenschlecht wird, das man eigentlich schon ein CO2 Zertifikat braucht, damit hätte ich nicht gerechnet.

      Speicherbedarf auf der Pladde: 8MB!

      Fazit: CD hat eine grottenschlechte Performance und einen noch schlimmeren Overhead. Solange man immer schön granuliert Objekte liest und schreibt, merkt man da wenig. Die standard "Employe Liste" in ner TableView durchzuscrollen ist ja auch wirklich nix was schnell gehen müsste. Wenn du aber wirklich mal viele Objekte auf einmal lesen oder schreiben musst (die Employes z.B. mal alle in ein PDF exportieren), frägst du dich, wer den Scheiß erfunden hat.

      Mit einem freundlichen "Jehova"

      Manfred
      Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
    • Wie geschrieben: fetch requests mit vielen Top-Level-Objekten sind böse. :P
      Immer schön granuliert Objekte lesen und schreiben. ;)
      «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

      Iä-86! Iä-64! Awavauatsh fthagn!

      kmr schrieb:

      Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
    • In meiner ersten CD basierten App hatte ich auch das Problem eines ungünstigen Objektgraphen, was ich erst bei > 100000 Objekten (inkl Beziehungen) bemerkt habe. Im Update habe ich den Baum verbessert und fetche analog zum iOS erstmal nur das, was der Benutzer sieht, und nur faults wo immer möglich. Dann fetche ich sofort im Hintergrund den Rest nach... geht sehr schön mit fetchLimit und Co.

      sprich, mit etwas Überlegen und Profilen lässt sich auch CoreData massiv beschleunigen. Natürlich muss der Baum stimmen. Daher kann ich mich nur Lucas anschliessen!

      Volker
    • Weil ich gerade so schön in Fahrt bin:

      Kundenprojekt, ein Hersteller für Schwimmbadtechnik. Bei so nem Becken muss viel gewartet, kontrolliert und protokolliert werden. Alle paar Stunden die Temperatur, Jodwerte, Antibiotikakonzentration, irgendwelche Chemikalien die dann da rein kommen und und und. Das soll aufs iPad. War sehr interressant, der Job.

      Manfred, gib CoreData mal wieder ne Chance!

      Funktioniert alles prächtig, solange man nur ein paar sichbare TableViewCells anmalen muss, die sich im Zeitlupentempo bewegen.

      "Wir hätten in der nächsten Version gerne einen Jahresbericht als PDF, nach Becken und Datum sortiert"

      Alle Einträge für ein Jahr fetchen, Becken "gruppieren" und sortieren und in einen PDF Context pinseln.

      2.0 war mit SQLite gemacht, den "Umbau" hab ich auf meine Rechnung genommen.
      Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
    • Manfred Kreß schrieb:

      Alle Einträge für ein Jahr fetchen, Becken "gruppieren" und sortieren und in einen PDF Context pinseln.

      Wenn die einzige starke Entity 'Geschäftsjahr' heißt wäre das ein Fetch für genau einen Eintrag...
      Der Rest ist 'Objekte im Speicher durchackern'.
      :-P ;-)
      «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

      Iä-86! Iä-64! Awavauatsh fthagn!

      kmr schrieb:

      Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
    • Fetch-Requests kennen Prädikate (WHERE), Gruppierungen (GROUP BY) und Sortierungen (SORT). Ohne es probiert zu haben: Wenn man das in Core Data sauber baut, dürfte da als SQL exakt das herauskommen, was Manfred als SQL getippt hat.

      Wenn man das natürlich im Code macht, funktioniert das nicht. Das liegt dann aber schlicht daran, dass man sich mit SQL besser auskennt als mit Core Data.
      Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
      25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?