PHP / MySQL OOP: Laden komplexer Objekte aus SQL

8

Ich arbeite an einem Projekt für einen Makler. Ich habe die folgenden Objekte / MySQL-Tabellen in meinem Design:

%Vor%

Dies sind die Beziehungen zwischen den obigen Objekten.

%Vor%

Annehmlichkeiten, Bilder, Links, Dokumente und Ereignisse verfügen alle über die erforderlichen Fremdschlüssel in der Datenbank, um anzugeben, zu welcher Einheit / welchem ​​Komplex sie gehören.

Ich muss die notwendigen Objekte aus der Datenbank in PHP laden, damit ich sie in meinem Projekt verwenden kann.

Wenn ich versuche, alle Daten aus der Tabelle in einer Abfrage mit LEFT JOINS auszuwählen, bekomme ich ATENT (Anzahl der Links) * (Anzahl der Bilder) * (Anzahl der Dokumente) Zeilen für jedes Unikat Einheit. Fügen Sie Annehmlichkeiten und Ereignisse dazu hinzu und ich werde all diese * # Annehmlichkeiten * # Ereignisse für jeden Komplex bekommen ... Nicht sicher, dass ich versuchen möchte, das mit dem Laden eines Objekts in PHP zu tun.

Die andere Möglichkeit besteht darin, für jeden Komplex / jede Einheit jeweils eine separate SQL-Anweisung für Links, Bilder, Dokumente, Ereignisse und Annehmlichkeiten auszuführen

Meine Fragen sind wie folgt:

Wenn ich alle meine Tabellen korrekt indexiere, ist es wirklich eine schlechte Idee, 3-5 zusätzliche Abfragen für jeden Komplex / Einheit auszuführen?

Wenn nicht, wie sonst bekomme ich die Daten, die ich in ein PHP-Objekt laden muss. Idealerweise hätte ich ein Objekt wie folgt für Einheiten:

%Vor%

Ich brauche nicht IMMER all diese Informationen, manchmal brauche ich nur den Primärschlüssel des Komplexes, manchmal brauche ich nur den Primärschlüssel des Agenten usw. Aber ich dachte, der richtige Weg wäre, dies zu tun lade das gesamte Objekt jedes Mal, wenn ich es instanziiere.

Ich habe viel über OO PHP geforscht, aber die meisten (alle lesen) Online-Beispiele benutzen nur eine Tabelle. Das hilft offensichtlich nicht, da das Projekt, an dem ich arbeite, viele komplexe Beziehungen hat. Irgendwelche Ideen? Bin ich hier völlig daneben?

Danke

[AKTUALISIEREN]

Auf der anderen Seite, normalerweise am Front-End, das jeder sehen wird, brauche ich ALLE Informationen. Wenn zum Beispiel jemand Informationen über einen bestimmten Komplex haben möchte, muss ich alle Einheiten anzeigen, die zu diesem Komplex gehören, alle Bilder, Dokumente, Links, Ereignisse für den Komplex sowie alle Bilder, Dokumente und Links für die Einheit.

>

Was ich vermeiden wollte, war, während einer Seitenladung eine Abfrage auszuführen, um den Komplex zu erhalten, den ich brauche. Dann eine weitere Abfrage, um die 20 mit dem Komplex verbundenen Einheiten zu erhalten. Dann für jede der 20 Einheiten, eine Abfrage für Bild, eine andere für Dokumente, eine andere für Links, etc. Ich wollte sie alle auf einmal, mit einer Reise durch die Datenbank.

[EDIT 2] Beachten Sie auch, dass die Abfragen zum Auswählen der Bilder, Dokumente, Verknüpfungen, Ereignisse und Agenten aus der Datenbank ziemlich einfach sind. Nur grundlegende SELECT [Liste der Spalten] FROM [Tabelle] WHERE [primary_key] = [Wert] mit dem gelegentlichen INNER JOIN. Ich mache keine komplexen Berechnungen oder Unterabfragen, nur grundlegende Dinge.

[BENZIN] Nachdem ich alle Antworten auf meine Frage gelesen hatte, entschied ich mich, einen Maßstab für meine Entscheidung zu setzen. Ich lade alle Einheiten, die ich brauche. Dann, wie ich Bilder anzeigen muss, Dokument, blah blah, lade ich sie zu dieser Zeit. Ich habe 30.000 Testeinheiten mit jeweils 100 Bildern, 100 Dokumenten und 100 Links erstellt. Dann lud ich eine bestimmte Anzahl von Einheiten (ich begann mit 1000, dann 100, dann die realistischere 10), schleuderte sie durch und lud dann alle Bilder, Dokumente und Links ein, die mit der Einheit verbunden waren. Bei 1000 Einheiten dauerte es ungefähr 30 Sekunden. Bei 100 Einheiten dauerte es ungefähr 3 Sekunden. Bei 10 Einheiten dauerte es etwa 0,5 Sekunden. Es gab eine große Abweichung von den Ergebnissen. Manchmal mit 10 Einheiten würde es 0,12 Sekunden dauern. Dann würde es .8. Dann vielleicht .5. Dann .78. Es war wirklich überall. Es schien jedoch durchschnittlich etwa eine halbe Sekunde zu dauern. In Wirklichkeit könnte ich nur 6 Einheiten gleichzeitig brauchen, und sie könnten nur 10 Bilder, 5 Links und 5 Dokumente mit ihnen verbunden haben ... so denke ich, dass die "greifen Sie die Daten, wenn Sie es brauchen" Ansatz ist die beste Wette in einer solchen Situation. Wenn Sie jedoch alle diese Daten auf einmal benötigen, wäre es sinnvoll, eine einzige SQL-Anweisung zu erstellen, um alle Daten zu laden, die Sie benötigen, sodass Sie die Daten nur einmal durchlaufen (6700 Einheiten pro Sekunde benötigten 217 Sekunden) während die vollen 30.000 PHP keinen Speicher mehr hatten).

    
SpaDusA 28.08.2009, 20:24
quelle

5 Antworten

4
  

Wenn ich alle meine Tabellen richtig indiziere, ist es wirklich eine schlechte Idee, 3-5 zusätzliche Abfragen für jeden Komplex / Einheit auszuführen?

Kurz gesagt, nein. Für jede der verwandten Tabellen sollten Sie wahrscheinlich eine separate Abfrage ausführen. Das würden die meisten ORM-Systeme (Object-Relational Mapping / Modeling) tun.

Wenn Leistung wirklich ein Problem ist (und basierend auf dem, was Sie gesagt haben, wird es nicht sein), dann könnten Sie die Ergebnisse mit etwas wie APC, Memcache oder Xcache zwischenspeichern.

    
Rob Knight 28.08.2009, 20:42
quelle
0

Der Punkt von ORM besteht nicht darin, jedes Mal ganze Objekte zu laden. Es geht darum, dass Ihre App einfach und transparent auf Objekte zugreifen kann.

Wenn Sie das Einheitenobjekt benötigen, laden Sie das Einheitenobjekt und nur das Einheitenobjekt. Wenn Sie das Agentenobjekt benötigen, laden Sie es, wenn Sie es benötigen, nicht wenn Sie das Einheitenobjekt laden.

    
longneck 28.08.2009 20:36
quelle
0

Vielleicht sollten Sie darüber nachdenken, dies aufzubrechen.

Wenn Sie Ihr Objekt initiieren, erhalten Sie nur die Details, die Sie für das Funktionieren dieses Objekts benötigen. Wenn und wenn Sie mehr Details benötigen, dann gehen Sie und holen Sie sie. Du verteilst deine Ladung und verarbeitest diese Weise: das Objekt erhält nur die Last und die Verarbeitung, die es benötigt, um zu funktionieren, und wenn mehr benötigt wird, erhält es es dann.

Also, in Ihrem Beispiel - erstellen Sie zuerst den Komplex. Wenn Sie auf eine Einheit zugreifen müssen, erstellen Sie diese Einheit, wenn Sie den Agenten benötigen, und holen Sie sich diesen Agenten usw.

%Vor%     
Robert DeBoer 28.08.2009 20:45
quelle
0

Ich musste dieses Problem vor einer Weile angehen, als ich mein eigenes MVC-Framework als Experiment zusammenstellte. Um die Datenschichten zu begrenzen, die aus der Datenbank geladen werden, habe ich eine Ganzzahl an den Konstruktor übergeben. Jeder Konstruktor dekrementiert diese Ganzzahl, bevor sie an die Konstruktoren der Objekte übergeben wird, die sie instanziiert hat. Wenn es zu 0 wurde, würden keine weiteren Unterobjekte instanziiert werden. Dies bedeutet, dass der übergebene int die Anzahl der geladenen Ebenen war.

Wenn ich also nur ein Attribut des Unit-Objekts haben wollte, würde ich das tun:

%Vor%     
Lucas Oman 28.08.2009 20:45
quelle
0

Wenn Sie die Objekte "speichern" wollen, dh sie zwischenspeichern, laden Sie sie einfach in ein PHP-Array und serialisieren Sie sie. Dann können Sie es in der Datenbank, in Memcache oder anderswo speichern. Wenn Sie ein Label hinzufügen, können Sie es abrufen und einen Zeitstempel einfügen, damit Sie wissen, wie alt es ist (d. H. Aktualisiert werden muss).

Wenn sich die Daten nicht oder nur selten ändern, gibt es keinen Grund, mehrere komplexe Abfragen jedes Mal auszuführen. Einfache, wie zum Beispiel eine primäre, können Sie auch nur direkt auf die Datenbank zugreifen.

    
Brent Baisley 28.08.2009 20:49
quelle

Tags und Links