Homepage von Basti1012 = ,kreuz und quer ,zufalls Themen taglich
Hier im Forum bekommt ihr bei euren fragen schnelle hilfe.Hier geht es rund um das Web SeitenProgrammieren.Alles rund ums Javascript,Html,Php,Css und Sql.Auf fast allen Fragen haben wir eine Antwort.
Der Soforthilfe-chat verspricht das ,was sein Name sagt. Hier sind Leute Online die sofort ihre hilfe anbieten.Seht in der OnlineListe nach und wenn einer Online ist werdet ihr auch antwort bekommen. Admine ,Moderatoren und Helfer sind unsere Spezialisten in Sachen Web Programierung


Täglich neues Thema

2020-07-11 = 2020-07-10Targesid erstellt
Update config id und datum

24.09.2019 21:23:43

Gekonnt Redundanz vermeiden

Viele Sites im Web werden im Zuge des Web 2.0 immer mehr „driven by user content“ – die Community fügt also Beiträge hinzu und / oder kommentiert sie. Das bereitet auch beim Datenbank-Design mitunter Schwierigkeiten. Ich möchte am Beispiel einer Nachrichtencommunity erklären, welche Probleme hinsichtlich der Performance auftreten können, auch wenn man die Regeln des Entity Relationship Models konsequent angewendet hat und alles in der für die Praxis üblichen 3. Normalform ist.

Wir nehmen an, dass User selbst neue Artikel in die Datenbank hinzufügen können und dabei 0-n Bilder-URLs zu ihrem News-Artikel angeben können. Aus ERM-Sicht naheliegend wäre also eine 1:n-Beziehung von der Nachrichten-Tabelle auf die Bilder-Tabelle (1 Artikel kann mehrere Bilder haben, aber ein Bild gehört nur zu einem Artikel). Und hier kommt die Frage: Ist das wirklich die Beziehung, die uns performante Ergebnisse beschert oder schafft sie lediglich Redundanz (in Bezug auf eine solche Community)?

Wenn User URLs von Bildern angeben können, kann es auch sein, dass sie bei mehreren Artikeln die gleiche Bildurl verwenden. Und in genau diesem Fall entsteht Redundanz.
Besser wäre deshalb eine n:m-Beziehung zwischen Artikeln und Bildern, die über eine Zwischentabelle realisiert wird. Dadurch kann 1 Artikel mehrere Bilder haben, aber 1 Bild kann auch in mehreren Artikeln genutzt werden – und zwar ohne redundante Datenspeicherung.

Wie soll das nun aber beim Einfügen umgesetzt werden, schließlich schickt der User das Eintragsformular ab und dann muss schon alles eingetragen werden. Es gibt 2 Möglichkeiten: Entweder prüfen wir vor dem INSERT, ob die angegebene Bild-URL schon einmal vorhanden ist in unserer Bilder-Tabelle und verzweigen dann entweder zu einem INSERT des neuen Bildes und dem Eintrag in der Zwischentabelle oder eben nur zu dem Eintrag in der Zwischentabelle beziehend auf das schon vorhandene Bild.
Es geht allerdings sehr viel eleganter und weniger aufwendig: der INSERT-Befehl wird nämlich nur ausgeführt, wenn er gegen keinen PRIMARY- oder UNIQUE-Index verstößt. Zuerst legen wir deshalb einen UNIQUE-Index auf die Bild-URL, damit garantiert ist, dass auch wirklich keine Redundanz entsteht. Anschließend können wir über die Anwendung das gewünschte Ergebnis durch folgende Anweisung erhalten:

mysql_query("INSERT INTO bilder (bildurl) VALUES ('http://url.de/bild.jpg')"); mysql_query("INSERT INTO artikel_bilder (artikel_ID,bild_ID) VALUES (".$artikel_ID.",(SELECT ID FROM bilder WHERE bildurl='http://url.de/bild.jpg'))");

Die erste Query fügt das neue Bild nur hinzu, wenn nicht die gleiche URL bereits in der Datenbank vorhanden ist. Der zweite Befehl fügt dann den neuen Eintrag in der Zwischentabelle hinzu und holt sich die ID des gewünschten Bildes. Diese ID kann gleich der LAST_INSERT_ID() sein (nämlich, wenn das Bild noch nicht vorhanden war), muss aber nicht.

Wer insbesondere bei Text- oder Binärdatentypen darauf achten muss, dass keine doppelten Einträge vorkommen, kann allerdings keinen UNIQUE-Index verwenden (es geht schon, aber dann nicht auf den gesamten Text bzw. Blob sondern nur auf eine bestimmte Zeichen- bzw. Byteanzahl). In so einem Fall empfehle ich den Einsatz einer zusätzlichen Hash-Spalte, auf die man den UNIQUE-Index legt und in der man einen MD5-Hash des Textes / Binärinhaltes speichert (optimal wäre ein SHA1-Hash, da dieser überschneidungsfreier ist). Das aktualisieren dieses Hashes würde ich wiederum über einen Trigger lösen, damit der Hash auch nach Aktualisierungen stets aktuell ist. Wer eine MySQL-Version vor 5.0 verwendet, in der keine Trigger unterstützt werden, muss allerdings stets darauf achten, den Hash-Wert selbst (über die Anwendung) immer zu aktualisieren.

datenbank
Update tutorials angezeigt