PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : (Prinzip)Frage an SQL Profis:


Mr. Lolman
2015-08-26, 14:49:12
Wie weit sollte man die Normalisierung treiben?

Konkreter Fall:

- Tabelle mit 13000 Einträgen (wird in den nächsten 20 Jahren maximal auf 25000 anwachsen, eher aber weit darunter bleiben )

- In einer Spalte gibt es Werte von 0-4 (irgendwann kann theoretisch auch 5,6,7,... dazukommen)

- In der Businessapplikation soll eine Suche innerhalb der Tabelle mit Einschränkung auf diese Spalte möglich sein.


Mein (kontroverser) Lösungsansatz:

A) SELECT FROM [Tabelle] GROUP BY [besagte Spalte] um eine Combobox mit den Auswahmöglichkeiten 0-4 zu befüllen.


[B]Andere (vermeintlich bessere) Lösungen:

B) Die Auswahlmöglichkeiten 0-4 händisch hinterlegen.

C) Monatlich beim Befüllen der Datenbank eine zusätzliche Relationstabelle befüllen und die Auswahlmöglichkeiten aus der Relationstabelle ermitteln.



Wie seht ihr das? Ist A) tatsächlich schlechtes Design?

(Imo ists eher B). C) ist im konkreten Fall mMn eher übertrieben. V.a. hat man sich am GROUP BY gestört, obwohl die Ausführungszeit selbst auf lahmen SingleCore Server gerademal ~50ms beträgt. Eine andere zur Möglichkeit zur dynamischen befüllung wär: SELECT LEVEL-1 FROM DUAL CONNECT BY LEVEL <= SELECT MAX([besagte Spalte])+1 FROM [Tabelle]. Hat kein GROUP BY ist aber auch nicht schneller)

Gibts da überhaupt eine vernünftige Antwort zu dem Problem, oder läufts objektiv wohl doch darauf hinaus, dass ich offenbar ein paar (nicht weiter zu hinterfragende) interne Programmierrichtlinien verletzt hab und nun deswegen alle am herumspinnen sind?

registrierter Gast
2015-08-26, 15:10:04
Handelt es sich um eine hochfrequentierte, hochperformante Applikation? Oder ist die Applikation jetzt schon träge und langsam?
Wenn nein, dann ist Lösung A vollkommen ausreichend und schnell genug. Dann noch ein Key auf die Spalte drauf, fertig.

Jede fortschrittliche SQL Datenbank cached die Ergebnisse oft ausgeführter Queries. Bei 25000 Einträgen wird wahrscheinlich sogar die ganze Tabelle im Speicher gehalten. Meist langweilen sich Datenbanken ohnehin.

Alles andere führt unweigerlich zu Mehraufwand. So viel Mehraufwand, dass jede zusätzlich reingesteckte Stunde wahrscheinlich nie in irgendeiner Weise durch die Optimierung wieder reingeholt werden kann.
Mehraufwand geht zudem oft mit weniger Robustheit / mehr Fehleranfälligkeit / mehr Wartungsaufwand einher.

Siehe Lösung B oder C.
Ändern sich die Werte, hast du jedes mal eine halbe Stunde Aufwand.
Irgendwann wirst du vergessen, die Werte nachzupflegen oder du bist nicht da oder du steigst aus dem Projekt aus => Bäm, Fehler => verschwendete Zeit bei der Fehlersuche => schlechteres Standing beim Kunden, weil unnötiger Fehler => unnötige Zeit beim Kunden verschwendet.
Speziell Lösung C.
Eine zusätzliche Tabelle bringt dir nichts. Von den aktuellen ~50ms der Abfrage entfallen ~47ms auf Kommunikation mit der Datenbank.

Lösung A ist robust, einfach zu verstehen, ausreichend performant, leicht wartbar, leicht zu implementieren und damit wenig fehleranfällig.

interzone
2015-08-26, 16:12:48
Von meiner Seite klar Lösung A.
25 K Datensätze max ist eine sehr geringe Datenmenge, das sollte jedes moderne DBMS mühelös bewältigen.

Spätere manuelle Aufwände sollten möglichst vermieden werden; denn man vergisst nach ein Monaten schon einmal, das in dieser oder jener Stelle Abhängigkeiten existieren - vor allem in einem immer komplexer werdendem Umfeld.

Ben Carter
2015-08-26, 16:57:18
C und die und die Relationstabelle mittels Trigger auf der Haupttabelle befüllen und bei Bedarf auch entleeren. Somit kein manueller Aufwand und trotzdem gute Performance beim Abfragen.

lg Ben

mr coffee
2015-08-26, 19:48:16
C und die und die Relationstabelle mittels Trigger auf der Haupttabelle befüllen und bei Bedarf auch entleeren. Somit kein manueller Aufwand und trotzdem gute Performance beim Abfragen.

lg Ben

Naja, vermutlich wird der Trigger häufiger ausgeführt, als dass die Relationstabelle neu geschrieben werden müsste, was evtl. Performance-Nachteile nach sich zieht. Falls du keinen Key setzen kannst ist evtl. Distinct schneller.

Lösung A auch von meiner Seite aus.

Trap
2015-08-26, 19:54:57
Wie wäre es mit
SELECT DISTINCT C FROM T
?

twodoublethree
2015-08-26, 20:58:26
Ich würde C favorisieren und den Wert in der Tabelle einfach als Fremdschlüssel definieren, dann machst die Auswahl immer über ein paar wenige Datensätze und es ist am "saubersten" implementiert.

Andererseits wäre die Lösung von Trap auch nicht schlecht, wenn die Spalte indiziert ist kann das auch nie und nimmer 50ms dauern.

RattuS
2015-08-27, 00:25:16
Lösung A ist angemessen, wenn es sich bei den möglichen Werten um Enumerationen handelt, d.h. die Werte ändern sich nicht, benötigen keine zusätzlichen Informationen, werden gar nicht oder nur selten erweitert etc. Ob das für dich zutrifft, kannst du nur selbst entscheiden.

Im Zweifel aber immer die referenzielle Integrität sicherstellen. Fremdschlüssel mögen manchmal pain in the ass sein, sie halten das Schema aber stets sauber und flexibel.

Asaraki
2015-08-27, 00:33:30
Naja, vermutlich wird der Trigger häufiger ausgeführt, als dass die Relationstabelle neu geschrieben werden müsste, was evtl. Performance-Nachteile nach sich zieht. Falls du keinen Key setzen kannst ist evtl. Distinct schneller.

Lösung A auch von meiner Seite aus.

Wieso sollte der trigger öfters ausgeführt werden?

Wenn ich die ursprüngliche Frage beantworten soll brauche ich mehr Infos zu den Frequenzen (abfragen), dbms und Business Anforderungen .

Auf Richtlinien schießt man wenn man weiß was man tut ;)

medi
2015-08-27, 06:48:00
Solange die Werte numerisch und selbsterklärend sind seh ich keinen Sinn darin noch ne weitere Relationstabelle einzuführen ausser du willst gleich noch beschreiben für was die Werte stehen (Was ich wiederum bevorzuge - finde nichts nerviger als erst mal in irgend welchen Dokus nachschauen zu müssen, die dann vllt. noch nicht mal aktuell sind - Selbsterklärend FTW!). Tendiere somit auch zu A.

@Trigger: Da steht doch, dass die Tabelle nur einmal im Monat aktualisiert wird.

Asaraki
2015-08-27, 07:10:23
Solange die Werte numerisch und selbsterklärend sind seh ich keinen Sinn darin noch ne weitere Relationstabelle einzuführen ausser du willst gleich noch beschreiben für was die Werte stehen (Was ich wiederum bevorzuge - finde nichts nerviger als erst mal in irgend welchen Dokus nachschauen zu müssen, die dann vllt. noch nicht mal aktuell sind - Selbsterklärend FTW!). Tendiere somit auch zu A.

@Trigger: Da steht doch, dass die Tabelle nur einmal im Monat aktualisiert wird.

Das beantwortet doch meine Frage nicht. Ein trigger wird in diesem Fall höchstens geprüft aber da was soll denn da "öfters" ausgeführt werden, respektive wo kostet das irgendwas nennenswertes? Ist das auf "kleinen" dbms irgendwie anders gelöst? (Das ist jetzt arg oberflächlich)

Ganz allgemein ist eine relationstabelle in diesem Fall höchstwahrscheinlich eine gute Gelegenheit "frisch von der Schule" zu wirken (nicht böse gemeint :-))

Aber wie gesagt, ohne dir Abfragefrequenz zu kennen ist das alles nahe am Kaffeesatz lösen, aber das sind natürlich spannende Fragen :)

Mr. Lolman
2015-08-27, 08:39:39
Die Combobox versteckt sich in einer von unzähligen Masken (mit vielen Karteireitern). Die Maske wird nicht zwingend für den laufenden Geschäftsbetrieb benötigt, sondern eher zum mal "schnell wo nachsehen". Das passiert ein paar Mal am Tag, das Öffnen der besagten Maske dauert ~1 bis 2 Sekunden, die Combobox wird nur beim Öffnen befüllt, die darin hinterlegten Daten sind dann bis zum Schließen der Maske im Arbeitsspeicher.

Ben Carter
2015-08-27, 08:53:37
Und wie oft wird in die ursprüngliche Tabelle etwas geschrieben? Davon würde abhängen, wie oft der Trigger gefeuert wird. Bei +12.000 Datensätzen in 20 Jahren, nehme ich an, dass es äußerst selten passiert und nicht mehrmals pro Minute. Somit wäre ein Trigger vielleicht etwas over the top, aber sicherlich halbwegs effizient und vor allem wäre es eine saubere Lösung.

lg Ben

mr coffee
2015-08-27, 09:21:40
Ja klar - ich hab irgendwie unterschlagen, dass die Tabelle nur einmal im Monat geschrieben wird und die Werte (1-4) sich nicht dynamisch ändern können. Also voll am Thema vorbei. Dann ist die Trigger-Lösung sicherlich in Ordnung. Man könnte ja - falls man mehrere Combo-Boxen dieser Art hat, eine Tabelle anlegen, in welcher man die Werte der Comboboxen sammelt - eine Tabelle je Combobox fände ich unschön (also eine ID je Combobox).

registrierter Gast
2015-08-27, 09:53:08
Die Combobox versteckt sich in einer von unzähligen Masken (mit vielen Karteireitern). Die Maske wird nicht zwingend für den laufenden Geschäftsbetrieb benötigt, sondern eher zum mal "schnell wo nachsehen". Das passiert ein paar Mal am Tag, das Öffnen der besagten Maske dauert ~1 bis 2 Sekunden, die Combobox wird nur beim Öffnen befüllt, die darin hinterlegten Daten sind dann bis zum Schließen der Maske im Arbeitsspeicher.
Damit ist eigentlich alles gesagt.
Jedwede Implementierung einer Optimierung kostet mehr Zeit, als die Optimierung je wieder einbringen wird.
Wenn die Maske ein bis zwei Sekunden dauert, ist die Query (<50ms) auch gar nicht der Flachenhals. Da sollte man woanders optimieren - wenn überhaupt.
Lösung C brächte ohnehin keine Besserung der Performance. Eine mögliche optimierte Lösung müsste clientseitig erfolgen.

Asaraki
2015-08-27, 10:23:40
Kann ich so aus Betriebswirtschaftlicher Sicht absolut unterschreiben.

Lolman, wenn du willst können wir aber das theoretische Problem und die Vorteile der Lösungsansätze mal besprechen wenn dich das interessiert :) kannst dich auch per pm für einen Skypetalk melden, ist im Pingpong Systems imho eher ineffizient

PS : bin ein "Profi" wenn du das so willst und werde für das optimieren von dB-Design und Zugriffen bezahlt, auch wenns nur ein Teil meiner Arbeit ist

littlejam
2015-09-15, 20:49:42
Die Combobox versteckt sich in einer von unzähligen Masken (mit vielen Karteireitern). Die Maske wird nicht zwingend für den laufenden Geschäftsbetrieb benötigt, sondern eher zum mal "schnell wo nachsehen". Das passiert ein paar Mal am Tag, das Öffnen der besagten Maske dauert ~1 bis 2 Sekunden, die Combobox wird nur beim Öffnen befüllt, die darin hinterlegten Daten sind dann bis zum Schließen der Maske im Arbeitsspeicher.

Also das Groupen lassen oder ich persönlich find eher Traps Lösung "select distinct c from t;" besser.

Noch eins, wenns MySQL ist:
http://sqlfiddle.com/#!9/5deaa/2/0 :freak:

Bei so einer kleinen Tabelle alles umstricken ist vielleicht sauber, aber sinnlos.

Somit wäre ein Trigger vielleicht etwas over the top, aber sicherlich halbwegs effizient und vor allem wäre es eine saubere Lösung.

lg Ben
Trigger - zumindest bei MySQL - sind scheiße und meiner Meinung nach echt weit von "sauber" entfernt.
- unübersichtlich, sie verstecken sich ziemlich gut
- Replikation funktioniert nicht/umständlich
- online-schema-change nur noch manuell möglich
+ warscheinlich noch weitere Fallstricke, die mir gerade nicht einfallen

Effizient ja; oft auch eine super Abkürzung. Aber ein Albtraum was Wartung angeht.

Gruß

RattuS
2015-09-15, 23:23:59
+ warscheinlich noch weitere Fallstricke, die mir gerade nicht einfallen
Einige SQL-Tools kopieren Trigger beim Duplizieren von Tabellen heimlich mit. Die Referenzen im Trigger bleiben dabei auf den originalen Tabellen bestehen. Kaum hat man sich nun eine Tabelle zum "etwas ausprobieren" dupliziert (hier und dort etwas DELETE), schon sind die ganzen Datensätze von der Quelle gleich mit weg. #truestory ;D

Asaraki
2015-09-16, 08:19:29
Naja was meinst du mit heimlich? Trigger gehören ja schon zur Tabellendefinition und referenzieren natürlich eine eindeutige Tabelle. Klingt jetzt eher nach Schnellschuss statt nach wirklichem Problem. Außerdem probiert man natürlich nix auf nem produktiven system aus :D

Delete trigger sind aber mit Vorsicht zu genießen und sollten eigentlich nicht als billigen Ersatz für RI benutzt werden. Aber gute DBAs gibts auch nicht grad wie Sand am Meer :/

RattuS
2015-09-16, 21:08:40
Außerdem probiert man natürlich nix auf nem produktiven system aus :D
Touché. :D

Na ja, Trigger sind für den Effekt, den sie haben können, nicht augenscheinlich genug. Natürlich kann man argumentieren, dass ein gut durchdachtes Schema keine Konflikte auslöst, aber realitätsnah ist das nicht und schon gar nicht bei der Anforderungsflut in moderner Software.

Jedenfalls kenne ich keinen Entwickler, der sich lieber in eine tiefe Trigger-Chain einarbeitet als eine kompakte Transaktion vor sich zu haben. Aber schwarze Schafe gibt es überall. :whistle:

Asaraki
2015-09-16, 21:13:14
Man baut auch sicher keine Ketten aus Triggern, wenn es IRGENDWIE anders geht. Aber in meiner Erfahrung wird das Thema sowieso schlecht behandelt in den kleineren Softwarefirmen, statt einem zentralen DBA gibts dann eben ein Dutzend Entwickler die mit sehr unterschiedlichen Wissensstand an den DBs rumfummeln. Da ist der Gau quasi vorgesehen :D

Ben Carter
2015-09-17, 14:50:16
Alles eine Frage der Dokumentation. :)

littlejam
2015-09-17, 19:41:44
Alles eine Frage der Dokumentation. :)
Jopp, das löst alle Probleme :biggrin:

Gruß

Asaraki
2015-09-17, 20:39:47
Jopp, das löst alle Probleme :biggrin:

Gruß

Hör ich da Sarkasmus? :D Denn er hat völlig recht.

littlejam
2015-09-17, 21:14:02
Man baut auch sicher keine Ketten aus Triggern, wenn es IRGENDWIE anders geht. Aber in meiner Erfahrung wird das Thema sowieso schlecht behandelt in den kleineren Softwarefirmen, statt einem zentralen DBA gibts dann eben ein Dutzend Entwickler die mit sehr unterschiedlichen Wissensstand an den DBs rumfummeln. Da ist der Gau quasi vorgesehen :D
Du hast mit beiden Aussagen recht.
1. Man baut keine Triggerketten wenns anders geht, und es geht eigentlich immer Anders.
2. Wenn ein Dutzend Entwickler an den DBs fummeln ist der Gau vorprogrammiert (und wird dann idealerweise durch massiven Materialeinsatz abgemildert bzw. verschoben).
Die Top-Doku dokumentiert bestenfalls genau was schief läuft.

Ergo muss das...
Alles eine Frage der Dokumentation. :)
Entweder Sarkasmus oder Trollierung auf allerhöchstem Niveau sein.

Woraufhin ich - weil ich mir eine Antwort nicht verkneifen konnte - eine ebenso Niveauvolle Antwort formulierte.
Hör ich da Sarkasmus? :D Denn er hat völlig recht.
Und jetzt bin ich doch drauf reingefallen ;(

Gruß

Asaraki
2015-09-17, 22:19:21
Nein der Er bist du. DBs ohne Doku ist wie ein Oldtimer ohne Garage. Zum scheitern verdammt

Ben Carter
2015-09-18, 10:44:01
Sicherlich löst eine gute Dokumentation nicht alle Probleme, erst recht nicht, wenn viele Leute an der DB rumbasteln.

Aber gute Dokumentation + Leute, die sich an Vorgaben halten können, Dokumentation lesen und verstehen, hilft schon mal dabei, sehr viele Probleme zu lösen erst gar nicht entstehen zu lassen.

lg Ben