Wozu die Normalform [1.|2.|3.] (NF)
Erwin
- datenbank
0 Sven Rautenberg0 Erwin,1 Sven Rautenberg0 Rouven0 hkl
Hi Forum,
angeregt durch folgenden Thread kam mir folgende Frage: Warum sollte ich die [1.|2.|3.] Normalform nutzen? Es ist doch viel einfacher einen Datensatz zu selektieren, in dem _alle_ Informationen enthalten sind (sicher, es werden u.U. sehr viele Spalten). Wenn ich die [1.|2.|3.] Normalform nutze müssen doch permanent Joins verwendet werden, um an die relevanten Informationen zu gelangen, oder?
Warum also sollte ich meine Tabellen normalisieren?
Danke, Erwin
Moin!
Warum sollte ich die [1.|2.|3.] Normalform nutzen?
_Sollten_ solltest du, weil es besser ist. _Müssen_ mußt du nicht.
Es ist doch viel einfacher einen Datensatz zu selektieren, in dem _alle_ Informationen enthalten sind (sicher, es werden u.U. sehr viele Spalten).
Du mußt unterscheiden zwischen Informationen, die mit der primären Identifikation in einer 1:1-Beziehung stehen, und Informationen, die als 1:n oder gar n:m gespeichert werden müssen.
Bei 1:n kriegt man es vielleicht noch gerade so hin, ohne Normalisierung auszukommen, bei n:m dürfte es aber schon extrem unübersichtlich werden.
Außerdem vereitelst du ohne Normalisierung viele weitere Abfragemöglichkeiten, die sich gar nicht auf die primäre Identifikation beziehen, sondern auf die verknüpften Untertabellen.
Wenn ich die [1.|2.|3.] Normalform nutze müssen doch permanent Joins verwendet werden, um an die relevanten Informationen zu gelangen, oder?
Richtig, das ist der Sinn dabei. Du erreichst allerdings eine höhere Flexibilität zu Lasten eines etwas höheren Rechenaufwands.
Warum also sollte ich meine Tabellen normalisieren?
Dann mach doch einfach mal ohne Normalisierung. Wird nichts gutes bei rauskommen, wenn du die Daten in der Datenbank denn mal so richtig komplexen Analyen unterziehen willst.
- Sven Rautenberg
Hi,
danke für die Antwort.
Dann mach doch einfach mal ohne Normalisierung. Wird nichts gutes bei rauskommen, wenn du die Daten in der Datenbank denn mal so richtig komplexen Analyen unterziehen willst.
Könntest du evtl. ein Beispiel konstruieren, an dem sich das nachvollziehen lässt?
Ich bin gerade beim Datenbankdesign, und da stellt sich nun die Frage: NF, der nicht. Aktuell spricht alles dagegen, da ich längere Rechenzeiten unter allen Umständen vermeiden will, ich lasse mich aber auch eines besseren belehren ;-) - und jetzt kommt ihr.
Danke, Erwin
Moin!
Dann mach doch einfach mal ohne Normalisierung. Wird nichts gutes bei rauskommen, wenn du die Daten in der Datenbank denn mal so richtig komplexen Analyen unterziehen willst.
Könntest du evtl. ein Beispiel konstruieren, an dem sich das nachvollziehen lässt?
Ok. Du hast eine Datenbank, die folgende Inhalt abbildet:
Kunden, die Gegenstände kaufen. Ein Gegenstand gehört zu einem Lieferant und zu einer Warengruppe.
Das kannst du alles in eine Tabelle hauen:
Kundenname | Gegenstand | Lieferant | Warengruppe
Das loggt dann mehr oder weniger alle Vorgänge. Und dürfte vermutlich auch relativ schnell gehen beim Schreibvorgang.
Das Problem dabei ist nur: Wo ist deine Auswahlliste von Lieferanten, die existieren? Wo ist deine Liste von Warengruppen, die definiert wurden? Wie kriegst du es ohne diese separaten Listen performant hin, das Eingabeformular mit zwei entsprechenden Auswahllisten anzureichern?
Antwort: Gar nicht. Du müßtest, um zumindest alle bereits in der Tabelle existierenden Einträge bei "Lieferant" und "Warengruppe", ein "SELECT DISTINCT" oder "GROUP BY" ausführen - welches seinerseits erst einmal die GESAMTE Tabelle durchscannt, um dann doppelte Einträge zu eliminieren.
Klingt das noch in irgendeiner Weise vorteilhaft?
Ich bin gerade beim Datenbankdesign, und da stellt sich nun die Frage: NF, der nicht. Aktuell spricht alles dagegen, da ich längere Rechenzeiten unter allen Umständen vermeiden will, ich lasse mich aber auch eines besseren belehren ;-) - und jetzt kommt ihr.
DB-Design hängt immer von den Daten, ihrer Struktur, und der zu erfüllenden Aufgabe ab.
Da du davon noch nichts berichtet hast, kann man dir keinen Rat geben.
- Sven Rautenberg
Hello,
in Ergänzung zu Sven gebe ich dir noch ein weiteres Beispiel. Er zeigt dir die Analysevorgänge, ich zeige dir die Konsistenzprobleme, die sich in der Datenbanktheorie als Menge von Anomalien etabliert haben.
Nimm folgendes Beispiel: Du bist ein Händler und beziehst Produkte von verschiedenen Lieferanten. Diese verwaltest du in einer einzigen Tabelle:
Produktname|Preis|Lagerbestand|...|Lieferantname|Adresse|TelNr
Eines schönen Tages sitzt du am Rechner, blätterst gerade in deiner Produktliste, da fällt dir ein Liefant ins Auge und du denkst dir "da war doch was, der hatte mir doch geschrieben er hat eine neue Telefonnummer". Na gut, alles kein Problem, du schaust in dein Postfach findest die E-Mail, änderst die Telefonnummer und der Fall ist erledigt. Oder nicht? Nein, ist er nicht, denn beziehst du von diesem Lieferanten noch ein weiteres Produkt, hast du nun zwei verschiedene Kontaktinformationen zum selben Lieferanten - welche ist aktuell? wie stellst du sicher, dass nur diese verwendet wird? Alles Fragen von Dateninkonsistenz, die sich in diesem Fall aus der Redundanzspeicherung ergibt. Normalisiert wäre sowas nicht passiert...
Und was die Performance angeht: Leg halt hinterher einen View drüber - die Datenbank übernimmt die Verantwortung diesen View aktuell zu erhalten, dein Select sieht wieder aus wie eine Tabelle, die darunterliegenden Daten bleiben sauber.
MfG
Rouven
Hallo Erwin !
CREATE TABLE calls
{
-- id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
zeit TIMESTAMP DEFAULT 'CURRENT_TIME',
next_date DATETIME,
name VARCHAR(30) NOT NULL,
eaz VARCHAR(30) DEFAULT '001',
lieblingsblume VARCHAR(20)
-- PRIMARY KEY(id)
};
Jetzt ruft am 11.11. Annabel auf '-007' an.
Dto Barbara auf '-008'.
Dto Christine auf '-009'.
( Schliesslich ist Fasching ! )
Wie verhindert man jetzt Chistine auf der '008' zurueckzurufen und ihr Orchideen statt Astern mitzubringen ???
Kopiert man dann zu jedem Date die Lieblingsblume vom vorangegangenen ?
DROP TABLE IF EXISTS dates ;
DROP TABLE IF EXISTS blumen;
DROP TABLE IF EXISTS buddies;
CREATE TABLE IF NOT EXISTS buddies
(
id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
name VARCHAR(30) NOT NULL,
eaz VARCHAR(30) DEFAULT '001',
PRIMARY KEY(id)
);
--
-- Auch das koennte man natuerlich noch in zwei Tabellen aufteilen.
-- In welche und warum ?
--
CREATE TABLE IF NOT EXISTS blumen
(
id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
name VARCHAR(30) NOT NULL,
ranking INTEGER UNSIGNED NOT NULL,
buddy_id INTEGER UNSIGNED NOT NULL,
PRIMARY KEY(id),
UNIQUE INDEX (id, ranking),
FOREIGN KEY(buddy_id)
REFERENCES buddies(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS dates
(
-- id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
zeit TIMESTAMP DEFAULT 'CURRENT_TIME',
next_date DATETIME,
buddy_id INTEGER UNSIGNED NOT NULL,
-- PRIMARY KEY(id),
FOREIGN KEY(buddy_id)
REFERENCES buddies(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
Kennst Du die Martini-Werbung in der George Clooney vor der Tuer bleibt ?
Der hatte wohl seine Datenbank nicht normalisiert und oefter mal verrissen...
Gruesse
HoLger