/MySQL/PHP - Anzahl der Abfragen reduzieren
Jose
- programmiertechnik
Hallo,
ich arbeite gerade an einem Link-Directory für meine Homepage, so etwas in der Art von Yahoo, wo jeder
seine Lieblingslinks eintragen kann und alles dann in Haupt- und beliebig vielen Unterkategorien
organisiert ist. Jetzt möchte ich, dass neben jeder Kategorie die Anzahl der darin enthaltenen Unter- und
Unter-Unterkategorien etc. angezeigt wird. Dazu folgendes Beispiel:
Computer (4)
--------
Computer > Drucker
Computer > Drucker > HP
Computer > Drucker > Epson
Computer > Monitore
Befinde ich mich in der Hauptansicht, so soll nach obigem Beispiel für die Hauptkategorie Computer - 4 für
die darin enthaltenen Unterkategorien angezeigt werden. Befinde ich mich in der Kategorie Computer, soll
neben der Kategorie Drucker 2 angezeigt werden...
Mein Problem liegt nun darin, wie ich den Wert für die Unterkategorien möglichst effizient ermitteln kann.
Das Ganze basiert auf PHP/MySQL, es geht mir aber vor allem mal um einen theoretischen Ansatz. Ich habe
auch schon eine Lösung, die hat aber einen gravierenden Nachteil (dazu mehr weiter unten).
Meine Lösung:
Die Tabelle mit den Kategorien ist folgendermaßen aufgebaut catID, catParent, catName. Dabei ist catID der Primärschlüssel und catParent die id der darüberliegenden Kategorie.
Angenommen ich befinde mich in der Hauptansicht (cat=0), so könnte ich auf folgende Art und Weise die
Unterkategorien ermitteln:
Das Problem dabei ist, dass ich so sehr schnell sehr viele Abfragen beisammen habe. Hier hatte 'Kategorie 1' 1 Unterkategorie und 'Kategorie 2' 3 Unterkategorien und ich benötigte schon 7 Abfragen für das Ergebnis. Bei 10 Hauptkategorien mit jeweils 5 Unterkategorien wären das 61 Abfragen. Das scheint mir dann doch etwas viel und dürfte wohl ziemlich auf die Performance schlagen, oder?
Meine Frage an Euch nun, kennt jemand eine bessere Methode, um dieses Problem zu lösen? Ich bin mit MySQL noch nicht wirklich sattelfest und könnte mir vorstellen, dass es da einen effizienteren Lösungsansatz gibt.
Ich freue mich über jede Anregung!
Jose
-----
Der Kopf ist rund, damit die Gedanken ihre Richtung ändern können.
Meine Frage an Euch nun, kennt jemand eine bessere Methode, um dieses Problem zu lösen? Ich bin mit MySQL noch nicht wirklich sattelfest und könnte mir vorstellen, dass es da einen effizienteren Lösungsansatz gibt.
-------------------
Das ist bei MySQL tatsächlich nicht effektiv. Du wirst kein Verzeichnis finden, das den kompletten Baum per Datenbank auf einmal darstellt.
Besser ist hier die Anwendung von XML oder ganz einfach der Aufbau einer statischen HTML-Seite, die bei jeder neue Kategorie einmal neu aufgebaut wird. Wenn du trotzdem nicht auf die Datenbank verzichten willst, dann lies den Baum wenigstens aus einer HEAP-Tabelle aus, die vorher aus einer normalen MyISAM (nach (Neu-)Start der Datenbank) initialisiert wird.
Gruß Robert
-------------------
Halihallo Jose
Meine Frage an Euch nun, kennt jemand eine bessere Methode, um dieses Problem zu lösen? Ich bin mit MySQL noch nicht wirklich sattelfest und könnte mir vorstellen, dass es da einen effizienteren Lösungsansatz gibt.
Dem Hinweis von Robert kann ich nur entsprechen. Datenbanken sind nicht auf hierarchische
Daten getrimmt, XML bildet diese hierarchischen Strukturen schon wesentlich besser ab,
was jedoch nicht umbedingt heisst, dass es mit XML performanter umzusetzen ist.
Hast du wirklich eine derart verworrene und tiefe Verschachtelung, als dass sich dein
Problem als zu aperformant erweist? - Bekommst du evtl. mit einem Index[1] auf parentCat
bessere Ergebnisse?
Dein Problem lässt sich _nicht_ "schön" lösen[2], jedoch lässt es sich wesentlich
verbessern:
Jede Kategorie hat ein Attribut subcatCount, welches die Anzahl Unterkategorien
speichert. Dieses Attribut ändert sich _nur_ beim hinzufügen oder löschen einer
Unterkategorie, verschnellert jedoch die Abfrage um ein vielfaches. Natürlich ist diese
Information redundant (und das sollte eigentlich vermieden werden) und erhöht die
Fehleranfälligkeit und den Wartungsaufwand der Software, aber vielleicht ist das für
dich ein kleiner Preis für den Mehrgewinn an Performance?
[1] der für deine Aufgabenstellung wirklich zu empfehlen wäre, wenn du viele Kategorien
verwaltest.
[2] Es gibt in SQL keine Rekursion. Es sei denn, du verwendest ein Datenbanksystem,
welches sogenannte Stored Procedures unterstützt, was in deinem Fall nicht vorliegt. Und
auch wenn, so würde es dennoch nicht effizient verarbeitet werden können.
Viele Grüsse
Philipp