# Übernormalisierung einer MySQL-DB mit Adressdaten



## suntrop (3. November 2009)

Hallo,
ich hatte heute mit meinem Programmierer darüber diskutiert, ob in einer Adressdatenbank die PLZ der Mitglieder unbedingt in eine extra Tabelle ausgelagert werden müssen.

Er meint, zwecks Vermeidung von *Redundanzen*, aus *Speicherplatzgründen* und wegen besserer *Performance* die PLZ in eine eigene Tabelle zu schieben.

Ich sehe das etwas anders. PLZ Redundanzen rauben mir nicht den Schlaf - sind ja auch nicht per se böse. Speicherplatz haben wir ausreichend (wir speichern nicht auf Diskette  ). Was die Performance angeht … hmm da habe ich zu wenig Erfahrung. Kann mir jedoch Vorstellen, dass bei 300 bis (irgendwann im Jahr 2030) vielleicht mal 3000 Mitgliedern das nicht wirklich ins Gewicht fällt.

So in etwa sehen die Tabellen aus.

```
User:
id | vorname | nachname | id_anrede | id_email | telefon | strasse | id_plz | id_ort | datum
PLZ:
id | plz | id_ort
Ort:
id | ort
```

Mir geht es um eine dritte Meinung. Ich lasse mich gerne eines besseren belehren, falls ich falsch liege.

Würde mich über eine paar Antworten freuen.


----------



## Yaslaw (4. November 2009)

die PLZ ist relativ klein und man kann sie als Zahl deklarieren. Jeder Join zwieschen Tabellen verbraucht ebenfalls Performance.

Ich persönlich würde die PLZ und den Ort nicht normalisieren, gerade weil bei 3000 Einträgen die wahrscheinlichkeit, dass 2000 Orte gespeichert werdn gross ist.


----------



## suntrop (4. November 2009)

yaslaw, danke für deine Antwort. Das mit dem Join war mir gar nicht klar. Dachte das kostet nichts 



yaslaw hat gesagt.:


> die PLZ ist relativ klein und man kann sie als Zahl deklarieren.



PLZ war vorher als Zahl deklariert, dann wurde aber bei den mit Null beginnenden PLZ die Null vorne weggeschnitten.
Wie machst du das, dass die Null beibehalten wird?


----------



## Yaslaw (4. November 2009)

Hm.. MySQL bietet nix sinnvolles um eine Zahl als formatierten String auszugeben (oder mir ist niy bekannt).
Also als VARCHAR speichern oder im PHP formatieren.

Grundsätzlich braucht jedes JOIN Performance, weil er ja zu jedem Datensatz bei jeder Bafrage die dazugehörigen Informationen zuordnen muss. Je nach Index kann das schneller oder langsamer sein.

Grundsätzlich handhabe ich das mit der Normalisierung so:
- Alle Felder die ich mit einem DropDown meinem Datensatz zuweisen will -> Normalisieren
- Alle Inhalte die mehr als selten über  mehrere Datensätze geändert werden müssen -> Normalisieren

Also, PLZ und Ort wechslen alle 50 Jahre ev. einmal, aber nicht dauernd. Ich persönlich mache auf diese Felder auch keine Dropdowns -> ergo normalisiere ich beide nicht.

Aber eine allgemeingültie Lösung gibt es nicht.

Hier noch ienige Dinge zu Performance:
- Jede Funktion die auf ein Feld im SQL ausgeübt werden muss, ist schlecht für die Performance (also CAST, CONNCAT etc)
- bei vielen Daten mit Vernknüpfungen stehts die Daten eingrenzen und dann verknüpfen
- Indexe auf alle Felder legen die auf irgend eine weise durchsucht werden (als auch auf PLZ und Ort, da man sicher danach suchen will)


----------



## XChris (5. November 2009)

Ich würde sie normalisieren! Nicht aus Prinzip, sondern weil es Sinn macht.

Denn viele Orte haben mehre PLZ. Viel Spass wenn sich da mal was ändert.

Ein weitere Grund: Man weiß nie was kommt ;-) Ich kenne Deine Anwendung nicht. Aber vielleicht benötigst Du irgendwann auch die Zuordnung zum amtlichen Gemeindeschlüssel oder ein Geotacking. Macht sich mit normalsierten Tabellen sehr viel besser.

Die Perfromanze-Aussage von yaslaw ist so nicht ganz richtig. Der Performanzeverlust dürfte bei Abfragen kaum messbar sein. Aber er wird deutlich werden, wenn du konkurrierende schreibende Zugriffe auf den selben Ort MIT der selben PLZ auf einer Tabelle hast. Wenn da ne Sperre auf dem Tupel ist, merkst Du das bei EINER Tabelle sehr viel eher als bei zwei Tabellen.


Die einfachere Lösung ist nur auf den ersten Blick alles in eine Tabelle zu stopfen.

Chris


----------



## vfl_freak (5. November 2009)

Moin,

ich denke, dass in beiden Antworten ein Körnchen Wahrheit steckt, würde aber grundsätzlich auch eher der Argumentation von Chris folgen!

Wenn man sich mal den Wikipedia-Beitrag zur Normalisierung anschaut ( http://de.wikipedia.org/wiki/Normalisierung_(Datenbank) ), dann wird gleich zu Beginn am Beispiel "Adressdaten" deutlich gemacht, warum es Sinn macht, Ort und PLZ raus zunormalisieren !

Bei 300 (oder 3000) DS spielen Dinge wie Speicherplatz (mithin Redundanzen) und Performance IMHO sicher eher eine untergeordnete Rolle! 

Viel wichtiger finde ich die Vermeidung von Anomalien (bspw. durch sich widersprechende Daten), weil dies (wie dort geschildert) die Wartung einer Datenbank und die Wahrung der Konsistenz der Daten erschwert!

Ich erfahre das hier leidvoll jeden Tag in der Firma, wo durch unseren Chef vielfach derartige Dinge mit Füßen getreten werden. Da ist dann bei großen DB's das Chaos vorprogrammiert !

Gruß
Klaus


----------



## suntrop (5. November 2009)

XChris hat gesagt.:


> Denn viele Orte haben mehre PLZ. Viel Spass wenn sich da mal was ändert.



Darin sehe ich keinen Widerspruch zur "Ein-Tabellen-Lösung". Es kann doch User 1 Berlin-Mitte 10115 und ein anderer Berlin 10115 und wieder ein anderer Berlin 10179 notiert haben.

Was meinst du mit "... wenn sich da mal was ändert."? Es ziehen doch nicht alle User von Berlin nach München (viel zu teuer da).

Das Beispiel von Wikipedia stimmt zu wenig mit unserer DB überein (könnt ihr natürlich nicht wissen  ). Aber jedes Mitglied ist nur einmal drin und hat keine Aufträge, Produkte oder ähnliches.

Eines ist mir gestern noch eingefallen. Habe ich vorher nicht bedacht. Ich denke ich würde auch auf eine extra Tabelle ausweichen, wenn ich gekaufte Orte samt PLZ hätte. Aber diese Daten kommen von den Usern selbst und wenn die etwas falsch machen, dann wirkt sich das auf andere aus. Das finde ich fatal.


Grüße
- suntrop


----------



## vfl_freak (5. November 2009)

suntrop hat gesagt.:


> Darin sehe ich keinen Widerspruch zur "Ein-Tabellen-Lösung". Es kann doch User 1 Berlin-Mitte 10115 und ein anderer Berlin 10115 und wieder ein anderer Berlin 10179 notiert haben.


Das hängt sicher auch ein bißchen davon ab, was mit den Daten geschehen soll!
Was ist denn in Deinem Beispiel nun '10115'? 'Berlin' oder 'Berlin-Mitte' oder 'egal' 



suntrop hat gesagt.:


> Was meinst du mit "... wenn sich da mal was ändert."?


Na, ich würde mal sagen: neue Regierung ... neu Ideen 



suntrop hat gesagt.:


> Das Beispiel von Wikipedia stimmt zu wenig mit unserer DB überein (könnt ihr natürlich nicht wissen  ). Aber jedes Mitglied ist nur einmal drin und hat keine Aufträge, Produkte oder ähnliches.


Es sollte auch nur einmal drin - es sei denn, man kann sich bspw. mit unterschiedlichen Adressen anmelden !



suntrop hat gesagt.:


> Eines ist mir gestern noch eingefallen. Habe ich vorher nicht bedacht. Ich denke ich würde auch auf eine extra Tabelle ausweichen, wenn ich gekaufte Orte samt PLZ hätte. Aber diese Daten kommen von den Usern selbst und wenn die etwas falsch machen, dann wirkt sich das auf andere aus. Das finde ich fatal.



Aha, Du kaufst Orte 
Interessant  wie teuer sind die denn ? ? 

Im Ernst, bspw. kann man in der Stammdatentabelle ein Verzeichnis von PLZ und Ort hinterlegen und dann bei der Eingabe einer PLZ gleich den Ort vorblenden oder auch nur beide Eingabe auf Konsistenz prüfen.
Andernfalls würdest Du ja auch Eingaben wie 
10115 Berlin-Süd
oder 
55555 Berlin 
zulassen 

Gruß
Klaus


----------



## suntrop (5. November 2009)

vfl_freak hat gesagt.:


> Was ist denn in Deinem Beispiel nun '10115'? 'Berlin' oder 'Berlin-Mitte' oder 'egal'


egal, solange es nicht falsch ist (10115 Köln wäre z.B. falsch und 50500 Berlin auch).




vfl_freak hat gesagt.:


> Aha, Du kaufst Orte
> Interessant  wie teuer sind die denn ? ?


Nein, ich sagte ja wenn ich sie gekauft _hätte_. Aber Wowereit war nicht mal zu Gesprächen bereit – glaubt man sowas.




vfl_freak hat gesagt.:


> Andernfalls würdest Du ja auch Eingaben wie
> 10115 Berlin-Süd
> oder
> 55555 Berlin
> zulassen


Das ist leider so  Weil ich die User-Eingaben heranziehen muss, da keine vorher vorhanden sind.


----------



## XChris (6. November 2009)

> Darin sehe ich keinen Widerspruch zur "Ein-Tabellen-Lösung". Es kann doch User 1 Berlin-Mitte 10115 und ein anderer Berlin 10115 und wieder ein anderer Berlin 10179 notiert haben.
> 
> Was meinst du mit "... wenn sich da mal was ändert."? Es ziehen doch nicht alle User von Berlin nach München (viel zu teuer da).



Was könnte sich ändern ... ? * Die PLZ selbst! *

Das kommt hin und wieder vor. Es kann auch passieren, dass Du EINE Strasse mit mehren PLZ hast. Beispiel Landstrassen. PLZ Änderungen sind häufiger als man denkt.
Ich kenne wie gesagt Deine Anwendung nicht. Aber wenn Du jemals PLZ Kataloge bekommst und deine Daten mit diesen Abgleichen musst ... ich will da keine einzige Tabelle haben. Klar kann man das auch mit SELFJOINS machen. Aber wenn ich es mir ersparen kann, dann mache ich das.

Chris


----------



## Matthias Reitinger (6. November 2009)

yaslaw hat gesagt.:


> Hm.. MySQL bietet nix sinnvolles um eine Zahl als formatierten String auszugeben (oder mir ist niy bekannt).
> Also als VARCHAR speichern oder im PHP formatieren.


Es gibt mit ZEROFILL und LPAD schon mindestens zwei Methoden, das in MySQL zu erledigen.

Grüße,
Matthias


----------



## Stummi (10. November 2009)

Meine Meinung:
PLZ und Ortsname sind 1:1, in der hinsicht reichen da 2 Tabellen.


```
User:
id | vorname | nachname | id_anrede | id_email | telefon | strasse | id_ort | datum
Ort:
id | plz | name
```


----------



## Flo<H> (10. November 2009)

Stummi hat gesagt.:


> Meine Meinung:
> PLZ und Ortsname sind 1:1, in der hinsicht reichen da 2 Tabellen.



So nicht ganz richtig  
Schau dir beispielsweise mal die Postleitzahlen von München an...


----------



## vfl_freak (11. November 2009)

> So nicht ganz richtig
> Schau dir beispielsweise mal die Postleitzahlen von München an...



Moin,

doch, eigentlich schon ... davon ausgehend, dass Stummi meint, dass es zu _*einer PLZ*_ immer nur genau _*einen Ortsnamen*_ geben kann !

Etwa so:

```
Ort:
id | plz   | name
1    80000   München-Ost
2    80001   München-Süd
3    80002   München-West
4    80003   München-Nord
```
Dann ist über die jeweilige ID schon eine Eindeutigkeit gegeben (auch wenn als NAME jeweils _nur_ 'München' eingegeben wird) 

Gruß
Klaus


----------



## Flo<H> (11. November 2009)

Jein. Ich würde sagen eine PLZ ist eindeutig einem Stadtteil und einem Ort zugeordnet. Aber der Ort ist nicht eindeutig einer PLZ zugeordnet. Das heißt ein Ort kann viele Stadtteile und somit auch viele PLZs haben.

Aber wie spitzfindig man hier ist, ist jedem selbst überlassen. Wobei ich hier abhängig von der Anwendung entscheiden würde. Ist die Adresse nicht so wichtig und es erfolgen nicht viele Adresseingaben könnte eine Tabelle reichen. Ist der Hauptbestandteil der gespeicherten Daten die Adresse (vgl. Adressbuch) würde ich es wahrscheinlich normalisieren.

Hab gestern bei Alternate eine schöne Funktion gesehen, die sich mit normalisierten Tabellen recht einfach lösen lässt: bei Eingabe der PLZ wird diese automatisch geprüft und auch gleich der richtige Ort eingetragen.

mfg flo


----------



## vfl_freak (11. November 2009)

> Hab gestern bei Alternate eine schöne Funktion gesehen, die sich mit normalisierten Tabellen recht einfach lösen lässt: bei Eingabe der PLZ wird diese automatisch geprüft und auch gleich der richtige Ort eingetragen.



Moin,

und ? ? ? 
Verrätst Du sie uns 
Das klappt natürlich nur, wenn dort auch alle Großkunden- und Postfach-PLZ (etc.) erfasst sind ...

Im übrigen muss natürlich in der externen Tabelle (bspw. über entsprechende NODUP-Keys) sichergestellt sein, dass keine PLZ doppelt vorkommt ... also nicht so etwas :

```
Ort:
id | plz   | name
1    80000   München-Irgendwo
2    80000   München-Sonstwo
```

Dies hingehen stellt ja kein Problem dar :

```
Ort:
id | plz   | name
1    80000   München
2    80005   München
3    80010   München
4    80015   München
```
sondern bildet einfach nur die Realität ab 

Gruß
Klaus


----------



## Enumerator (11. November 2009)

Hi!



vfl_freak hat gesagt.:


> Bei 300 (oder 3000) DS spielen Dinge wie Speicherplatz (mithin Redundanzen) und Performance IMHO sicher eher eine untergeordnete Rolle!


Dem kann ich nur zustimmern. Dennoch ein paar Anmerkungen...



vfl_freak hat gesagt.:


> davon ausgehend, dass Stummi meint, dass es zu _*einer PLZ*_ immer nur genau _*einen Ortsnamen*_ geben kann


Das ist nicht richtig: Es gibt Postleitzahlen, die sich mehrere kleine Orte teilen - nicht nur in Deutschland.
Wobei wir beim nächsten Punkt wären - es ist schon fast unverschämt dem Ausland die Registrierung zu verweigern. Unabhängig davon ob die Seite Deutsch, Englisch oder Farsi ist. Gehen wir mal von Deutsch aus - was ist mit Österreichern, Schweitzern und sonstwo lebenden Deutsch-Sprechenden? In deren Land sieht eine Postleitzahl wahrscheinlich ganz anders aus. Und wo in den Tabellen oben ist eine Länder-ID? Oder zumindest Kürzel nach ISO 3166?

Also bei einer so geringen Anmelde-Quote ist es wirklich egal, wo und wie man die Postleitzahlen ablegt. Im Vordergrund steht doch eigentlich nur, dass man aus Rechts- und/oder Geschäftsgründen die Kontaktdaten der Mitglieder vollständig speichert. Mal davon abgesehen: Wie oft interessiert Euch denn die PLZ in Abfragen? Ich mein, Ihr schreibt doch sicher kein Telefonbuch-Ersatz, hm?

Gruß
Enum


----------



## suntrop (11. November 2009)

Danke euch für eure Antworten. Ist interessant zu lesen.



Enumerator hat gesagt.:


> Wobei wir beim nächsten Punkt wären - es ist schon fast unverschämt dem Ausland die Registrierung zu verweigern.


Kennst du meine Zielgruppe?


----------



## Enumerator (11. November 2009)

In Deutschland lebende die einen PC benutzen können, ihren Namen, Anschrift und sogar ihre Postleitzahl kennen? Das alles in Zeiten von Globalisierung und Pandemien von Dummheit? Wie zum Teufel willst Du da in 20 Jahren 3000 Nutzer zusammen kratzen? ;-]


----------



## XChris (12. November 2009)

PLZ und Ort sind keine 1:1 und auch keine 1:N Beziehung!

Eine PLZ und mehre Orte? Bitteschön:
http://www.plz-postleitzahl.de/land.thüringen/plz-99192.html

Ein Ort mit mehren PLZ? Bitteschön:
http://www.plz-postleitzahl.de/land.thüringen/16263/index.html

Und wenn man richtig sucht, findet man auch eine PLZ, welche zwei Orten zugeordnet ist und jeder dieser Orte auch mehre PLZ hat. 

Es ist eine schlechte Idee PLZ und Ort ohne Nachzudenken in eine Tabelle zu stopfen. Wenn ich nur Kundendaten verwalte: Okay. Aber sowie ich eine Auswertung machen muss, über Stadtgebiete und Zusammenhänge in irgendeiner Art, dann mache ich mir schon bei der Implementierung das Leben schwer.

Sondern leider eine n:mBeziehung. Ergo: Eigentlich sogar 3 Tabellen wenn man es wirklich vollständig normalsieren müsste.

Chris


----------



## suntrop (12. November 2009)

… hieße das, dass ich statt der PLZ und dem Ort bei jedem Mitglied eine ID aus der jeweiligen Tabelle eintragen würde?
Oder bräuchte ich eine Tabelle PLZ, eine Tabelle Orte und eine Tabelle in der ich dem User die ID für PLZ und Ort zuweise und trage beim Mitglied die ID aus dieser letzten Tabelle ein?


----------



## vfl_freak (13. November 2009)

suntrop hat gesagt.:


> … hieße das, dass ich statt der PLZ und dem Ort bei jedem Mitglied eine ID aus der jeweiligen Tabelle eintragen würde?



Moin,

genau 

Über die ID wird dann die entsprechende Kombi aus PLZ/Ort gezogen !

Gruß
Klaus


----------



## suntrop (13. November 2009)

… dann habe ich es doch nicht verstanden 

Ich trage beim Mitglied nur eine ID ein, die wiederum die Kombination enthält?! Wo wird die Kombination "erstellt"? Hast mich erfolgreich verwirrt


----------



## vfl_freak (16. November 2009)

suntrop hat gesagt.:


> Ich trage beim Mitglied nur eine ID ein, die wiederum die Kombination enthält?! Wo wird die Kombination "erstellt"?



Moin,

na, halt die Kombination, die mit dieser ID als Key in der zweiten Tabelle steht - das ist genau dass, was man (u. a.) als DB-Normalisierung bezeichnet 

Gruß
Klaus


----------



## suntrop (17. November 2009)

Ich hab das ganze mal (für mich und vielleicht den ein oder anderen) mal grafisch dargestellt.

Ich denke das richtig richtige ist dann 1-plus-3.png (1 User Tabelle + 3 Tabellen mit PLZ, Ort und der Kombi). Die Grafik 1-plus-2.png wäre nur halb richtig.


----------

