Ich muss eine Anwendung pflegen, die viele Spalten vom Datentyp text enthält, in die mehrere Werte eingefügt werden, die durch Kommas, Schrägstriche oder manchmal sogar durch das Pipe-Zeichen (|) voneinander getrennt sind. Ich versuche herauszufinden, warum du das jemals auf der Erde tun würdest.
Zum Beispiel hat eine Bestellungstabelle eine Spalte namens details, die Informationen wie folgt enthält:
%Vor% wobei die /
die Werbebuchungen trennt; Es gibt VBScript-Code, der den Wert aus einem Re-Cord-Set liest und in einer For
-Schleife für die Anzeige mit etwas wie (und das ist ziemlich genau, wie der Code liest, Variablennamen und alle) arydtls = split(rstmp("details"), "/")
analysiert. Diese Methode wird im gesamten Code für verschiedene Tabellen wiederholt.
Es scheint mir, als wäre es 100x besser (um nicht zu sagen, einfacher zu arbeiten), nur die Details in einer separaten Tabelle zu haben und zurück zu verlinken (komischerweise, für Orders tut Tun Sie dies, aber die Daten stimmen nicht immer mit dem Textfeld "Details" überein, da die Tabelle "OrderDetail" im Code aktualisiert wird. Das Feld "Details" wird in der Anwendung als schreibgeschützt behandelt.
Weiß mein Vorgänger etwas, was ich nicht getan habe, oder soll ich "WTF? !!" sagen? wenn ich mir dieses Schema anschaue? Es scheint, als wäre es wahnsinnig ineffizient und schwierig, so zu warten, und es macht das Ausführen von Berichten besonders schwierig, weil die Daten, die ich brauche, in Textfeldern ODER in einem von zwölf Tabellen mit ähnlichen Informationen enthalten sein können Teile der Anwendung.
Weiß mein Vorgänger etwas, was ich nicht getan habe, oder soll ich "WTF? !!" sagen? wenn ich mir dieses Schema anschaue?
Nein, Ihr Vorgänger hat es nicht getan. Ja, du hast recht. Siehe Hinweis am Ende jedoch.
Es scheint so, als wäre es wahnsinnig ineffizient und schwierig so zu warten, und das macht das Ausführen von Berichten extrem schwierig, weil die Daten, die ich brauche, in Textfeldern enthalten sein könnten ODER in einem von einem Dutzend Tabellen, die ähnliche Informationen enthalten in verschiedenen Teilen der Anwendung verwendet.
Es ist wahnsinnig ineffizient. Siehe Hinweis am Ende jedoch.
Eine Spalte sollte immer ein unteilbares Attribut der Zeile sein. Ich sehe zwei Kopien von drei (vielleicht vier) Attributen in dieser Spalte:
%Vor%Dies wäre besser als entworfen worden:
%Vor%HINWEIS:
Es ist möglich, dass dies getan wurde, um historische Informationen angesichts sich ändernder Werte an anderer Stelle in der Datenbank zu bewahren. Zum Beispiel, wenn sich die Beschreibung einer Lagerposition ändert oder der Artikel gelöscht wird.
Aber das ist immer noch nicht der richtige Weg, damit umzugehen. In diesem Fall hätten Fremdschlüsseleinschränkungen verhindert, dass der Artikelcode gelöscht wurde, und Prozesse hätten eingerichtet werden sollen, um zu verhindern, dass die Beschreibung aktualisiert wird (z. B. Versionsverwaltung der Lagerartikelcodes).
Natürlich, wenn Sie nie nach einem der Elemente in dieser Spalte suchen, ist das vollkommen richtig, obwohl es in Bezug auf mögliche zukünftige Funktionalität unklug ist, nach ihnen zu suchen.
Vielleicht ist das einzige, was jemals in dieser Tabelle gesucht wurde, der Kundencode - dann reicht ein Textfeld mit freiem Format aus.
I würde es immer noch nicht so machen, aber ein YAGNI-Argument kann gemacht werden, dass es besser wäre, das DB-Schema in der Zukunft zu ändern, falls und wenn diese Suchfunktionalität hinzugefügt werden muss .
Die zwei wahrscheinlichsten Szenarien sind:
Da die Normalisierung bei Abfrageoperationen oft sehr teuer sein kann, können wir manchmal Leistungssteigerungen erzielen, indem wir einen teuren Join eliminieren und die Manipulationen auf der Anwendungsseite gegen eine einzelne Zeile ausführen.
Es gibt keine absolute Regel für das Datenbankdesign, die besagt, dass "das Speichern von Begrenzungswerten in einer einzelnen Zeile für dieses Szenario besser ist". Es geht darum, gegen Ihre spezifischen Datensätze und Ihre Nutzungsmuster zu testen und gegebenenfalls Verbesserungen vorzunehmen.
Nach meiner Erfahrung ist es nicht sehr üblich, dass dieses Muster eine Verbesserung gegenüber der Normalisierung darstellt ... aber das ist ziemlich untypisch.
Bearbeiten: Eine dritte Möglichkeit besteht darin, dass die n-Werte pro Zeile eine Änderung gegenüber dem ursprünglichen Schema darstellen. Anstatt eine neue Tabelle hinzuzufügen, hat der Vorgänger die Größe der Spalte geändert. Das unterscheidet sich nicht unbedingt von der "inkompetenten" Option :), aber es gibt manchmal politischen Druck bei Änderungen des Datenbankschemas ...
Wenn die Daten nur zur Information dienen und "sich nie ändern" , wie Sie so oft hören, dann könnte es ein schneller Gewinn gewesen sein, nur um eine Anzeigekette direkt zum Feld zu werfen. Schließlich ist das Ersetzen von Rohren mit Tabs und Schrägstrichen mit BRs, um es auf den Bildschirm zu bringen, unglaublich einfach. Wenn der Code extrem schnell geschrieben wurde, dann könnte dies die einfachste Option gewesen sein.
Ein neues Feature seit SQL 2005 ist der XML-Datentyp. Eine wichtige Verwendung davon ist, dass Sie eine unbekannte Anzahl von Werten für einen bestimmten Datensatz speichern und indizieren können. Du magst dich für die Farbe eines Dinges interessieren, für die Dimensionen eines anderen, für das Gewicht von etwas anderem. Sie können möglicherweise keine definitive Liste dieser Dinge erstellen und eine wirklich normalisierte generische Methode zum Speichern dieser Daten kann für das System zu langsam oder zu kompliziert sein. Dies könnte eine Arbeit gewesen sein, um ähnliche Funktionalität zu versuchen.
Der Schlüssel hier ist, die meisten Dinge sind aus einem bestimmten Grund getan. Du hast es richtig betrachtet, als du versucht hast, diesen Grund herauszufinden. Du könntest eines Tages darüber hinwegkommen und denken "Oh yeah!". Wenn man etwas aus seiner eigenen Perspektive betrachtet, kann dies oft dazu führen, dass man das Szenario "Wald für Bäume" nicht sehen kann.
Ihr Vorgänger hatte vielleicht ein paar andere Ideen und das war unvollendet?
Ich kann Ihnen sagen, dass dies sehr schlecht für die Leistung ist
Wie würden Sie eine Abfrage erstellen, die zurückgibt, wer ein blaues Widget gekauft hat? Sie müssen die gesamte Tabelle scannen und dann diese Information analysieren, wenn es eine andere Tabelle gab und diese normalisiert wurde, dann wäre dies viel leistungsfähiger
Ich habe eine Datenbank in einer bestimmten Unternehmenssoftware gesehen, in der es viele Orte gibt. Es ist ziemlich schrecklich, sowohl aus Sicht der Wartung als auch aus Performance-Sicht. Die genannten Gründe sind im Allgemeinen:
Nun, der erste Punkt ist wahrscheinlich wahr, aber es ist nur "einfacher", bis Sie dagegen abfragen wollen. Jetzt bist du verrückt. Also würde ich sagen, das ist effektiv widerlegt. Der zweite Punkt ist wieder wahr, solange Sie nicht dagegen fragen. Sobald Sie die gesamte Tabelle einlesen, analysieren Sie die Daten, dann tun Sie das Filtern von Zeilen in Ihrer App, verlieren Sie. Der letzte ist immer wahr, aber wen interessiert es, wenn die Datenbank "überladen" ist? Dafür ist es da! Mit anständigen RDBMS können Sie Ihre Tabellen trotzdem in mehrere Schemas einfügen, die den Namespaces ähneln und die Unordnung bekämpfen. Eine gute Benennungskonvention hilft auch (aber wenn Sie ungarische Warzen verwenden, so helfen Sie $ Gottheit).
Kurz gesagt, es ist eine schlechte Idee. Ich hoffe, du darfst es reparieren, aber höchstwahrscheinlich wirst du es nur mit seinen ursprünglichen Bedingungen behandeln müssen ...
In Betriebssystemen wie Universe werden UniData-Daten in Dateien gespeichert, die durch etwas wie
begrenzt sindChar (254) = trennt die Eigenschaften Char (253) = trennt mehrere Werte in einer Eigenschaft Char (252) = trennt Sub-Sub-Werte und so weiter
Schockierend ist es nicht :-) Immer wenn ich mit ehemaligen Kollegen rede, die noch mit DataBasic arbeiten und sie fragen, welche DB ich benutze, ist die erste Frage, die sie stellen, "Behandelt sie Multi-Werte in Ordnung?"
In einem RDBMS würden wir eine Auftragstabelle und eine OrderLine-Tabelle haben. Die PK auf der OrderLine wäre höchstwahrscheinlich etwas wie OrderNumber, LineNumber.
In UniData usw. würden sie eine Eigenschaft in der Reihenfolge "Lines" haben, die eine Liste von Schlüsseln für die OrderLine-Datei enthält, wobei der zusammengesetzte Schlüssel normalerweise durch ein Sternchen getrennt ist.
Wenn sie ihre Reihenfolge aus der Datei in den Speicher laden, haben sie eine Liste von Schlüsseln, die sie brauchen, um OrderLines aus der OrderLine-Datei zu laden. Beachten Sie, dass dies Dateien und keine Tabellen sind: -)
Es sieht für mich so aus, als ob jemand, der mit dieser alten Art der Datenspeicherung vertraut ist, versucht hat, eine relationale Datenbank zu benutzen, sie überhaupt nicht zu verstehen und dann versucht hat, sie wie UniData funktionieren zu lassen.
Entsorge sie: -)
Ich kann nicht sagen, was Ihr Vorgänger dachte. Wie Rex M sagte, führt manchmal politischer Druck zu seltsamen Implementierungen.
Sehr viele Leute, die eine Liste von Items in einen einzigen Wert in Tabellen stopfen, versuchen, die Einschränkungen der (ersten) normalen Form zu umgehen. Der Nachteil ist, dass Abfragen in der App programmatisch durchgeführt werden müssen, anstatt ein einfaches Citerion in einer WHERE-Klausel zu verwenden.
Vor etwa zehn Jahren hat Oracle die Möglichkeit hinzugefügt, eine Tabelle in einen Wert zu setzen. Etwa zur selben Zeit hat Date 1NF neu definiert, so dass alle Relationen automatisch in 1NF sind. Dies schließt auch andere Beziehungen ein. Ohne dieses Feature besteht das einfachste und leistungsstärkste Design darin, das wiederholte Element in einen separaten Wert mit einer Zeile für jedes Element zu zerlegen.
(Beispiel: eine Liste von Kursen, für die ein Kursteilnehmer eingeschrieben ist)
In vielen Fällen ist die Wurzel Coauses Ignoranz oder Sturheit der Designer. Auch hier weiß ich nicht, welchen Einschränkungen Ihr Vorgänger gegenüberstand. Simuliere ihn nicht, es sei denn, du musst es tun.
Warum würden Sie so etwas tun?
Zurück über mumble vor Jahrzehnten, arbeitete meine Frau auf dem Pick-System, das eine Datenbank und ein BASIC und dergleichen enthalten. Die Auswahl Datenbank und Sprache funktionierte gut mit Arrays in Datenbankfelder (nicht sicher, ob ich sie Spalten nennen sollte). Es gab also eine Umgebung, in der dies vollkommen Sinn machte.
Ich weiß nicht, ob Pick immer noch da ist, aber ich habe schon lange nichts mehr davon gehört. Es ist möglich, dass diese Tabelle eine Pick-Datenbank war, die (schlecht) in eine SQL-basierte Datenbank übersetzt wurde, und es war möglich, dass derjenige, der sie schrieb, ein früherer Pick-Entwickler war, der nicht gelernt hatte, eine relationale Datenbank zu benutzen. p>
Das letzte Mal, als ich in eine Datenbank wie diese gerannt bin, habe ich gefragt. Es stellte sich heraus, dass es von einem ehemaligen Pick-Entwickler entworfen wurde.
Ich würde dieses Design nicht als kompetent bezeichnen, es sei denn, dass dies wirklich als schreibgeschütztes Feld gedacht war, aber es könnte gut sein, dass der Designer nicht dumm war.
Ein möglicher, irgendwie gültiger Grund könnte sein, dass die Datenstruktur nicht fest ist , die Detailattribute bei Auftragsinstanzen sehr unterschiedlich sind.
Es ist nicht einfach, mit dynamischen Attributen in einer statischen Struktur wie der Datenbank zu arbeiten. Eine XML-Struktur ist zum Beispiel für ein solches Szenario besser geeignet, aber mit der inhärenten Ausführlichkeit der XML-Datei könnte der "csv like" -Ansatz eine attraktivere Alternative gewesen sein.
Sieht für mich wie ein WTF aus. Es ist nicht konsistent mit der Implementierung anderer Tabellen und es ist definitiv nicht effizient. Und wenn Sie sich das Schema ansehen, ohne die darin enthaltenen Daten zu kennen, wäre es leicht, den Sinn einer Spalte zu missverstehen.
Es könnte jedoch einen Grund dafür geben, warum der frühere Entwickler dies getan hat. Könnten Sie uns mehr Informationen geben, wie auf der Geschäftslogik? Danke
Tags und Links database-design