Ertrinken in einem Meer von Nullen

8

Eine Anwendung, die ich geerbt habe, verfolgt Labortestergebnisse, die an Materialproben durchgeführt wurden. Daten werden in einer einzigen Tabelle (tblSampleData) mit einem Primärschlüssel von SampleID und 235 Spalten gespeichert, die potenzielle Testergebnisse darstellen. Das Problem ist, dass pro Probe nur wenige Tests durchgeführt werden, so dass jede Zeile mehr als 200 Nullen enthält. Tatsächlich gibt es eine zweite ähnliche Tabelle (tblSampleData2) mit weiteren 215 hauptsächlich Null-Spalten und einem Primärschlüssel von SampleID. Die beiden Tabellen haben eine Eins-zu-Eins-Beziehung, und die meisten SampleIDs enthalten einige Daten in beiden Tabellen. Für jede SampleID gibt es jedoch leicht 400 Nullspalten!

Ist das ein schlechtes Datenbankdesign? Wenn ja, welche Normalformregel ist gebrochen? Wie kann ich diese Tabelle abfragen, um festzustellen, welche Spaltengruppen normalerweise zusammen mit Daten gefüllt werden? Mein Ziel wäre es, 45 Tabellen mit 10 Spalten und weniger Nullwerten zu haben. Wie kann ich das machen? Wie vermeide ich es, bestehende Anwendungen zu brechen?

Die Tabellen enthalten bisher etwa 200.000 Stichproben. Benutzer bitten mich, weitere Spalten für weitere Tests hinzuzufügen, aber ich möchte lieber eine neue Tabelle erstellen. Ist das klug?

    
DeveloperDan 01.07.2010, 12:33
quelle

10 Antworten

1

Ich bin mir nicht sicher, ob das Design wirklich so schlecht ist. NULL-Werte sollten eigentlich relativ günstig zu speichern sein. In SQL Server gibt es für jede Zeile ein internes Bitfeld (oder Felder), das angibt, welche Spaltenwerte NULL sind.

Wenn die Leistung der Anwendung nicht verbessert werden muss und der Kostenvorteil beim Refactoring aufgrund der Änderung des Tabellenschemas nicht positiv ist, warum sollte es geändert werden?

    
Kenny Evitt 01.07.2010, 13:00
quelle
9

Ich habe Artikel / Artikel gesehen, die darauf hindeuten, dass einfach NULL in der Datenbank das erste normale Formular bricht.

Nach dem, was ich aus Ihrer Beschreibung der Datenbank gesammelt habe, könnte ein besseres Design wie folgt aussehen:

Eine Beispieltabelle mit Feldern, die immer einem Beispiel zugeordnet sind. Zum Beispiel

%Vor%

Dann eine Tabelle mit Testtypen mit einem Eintrag für jeden Testtyp, der ausgeführt werden kann.

%Vor%

Schließlich haben Sie eine Zwischentabelle, die die Viele-zu-Viele-Beziehung zwischen den beiden obigen Tabellen darstellt und die Ergebnisse für die Tests enthält.

%Vor%

Dies würde die Nullwerte eliminieren, da die Tabelle TestResult nur Einträge für die Tests enthalten würde, die tatsächlich für jede Probe durchgeführt wurden. Ich habe einmal eine Datenbank für einen fast identischen Zweck entworfen, was ich glaube, was Sie tun, und das ist der Ansatz, den ich gewählt habe.

    
NYSystemsAnalyst 01.07.2010 12:49
quelle
4

Sie könnten das bekannte Entity-Attribut-Value-Modell (EAV) verwenden. Die Beschreibung, wann EAV verwendet werden sollte, passt gut zu Ihrem Anwendungsfall:

  

Diese Datendarstellung ist analog zu space-effizienten Methoden zum Speichern einer dünn besetzten Matrix, wo nur nicht leere Werte gespeichert werden.

     

Ein Beispiel für die EAV-Modellierung in Produktionsdatenbanken ist der klinische Befund (Vorgeschichte, aktuelle Beschwerden, körperliche Untersuchung, Labortests, spezielle Untersuchungen, Diagnosen), der für einen Patienten gelten kann. Über alle medizinischen Fachgebiete hinweg können diese Hunderttausende umfassen (mit neuen Tests, die jeden Monat entwickelt werden). Die Mehrzahl der Personen, die einen Arzt aufsuchen, hat jedoch relativ wenige Befunde.

In Ihrem speziellen Fall:

  • Die Entität ist eine Materialprobe.
  • Das Attribut ist ein Testtyp.
  • Der Wert ist das Ergebnis eines Tests für eine bestimmte Stichprobe.

EAV hat einige schwerwiegende Nachteile und schafft eine Reihe von Schwierigkeiten, so dass es nur angewendet werden sollte, wenn es angemessen ist. Sie sollten es nicht verwenden, wenn Sie alle Testergebnisse für eine bestimmte Probe in einer einzelnen Zeile zurückgeben müssen.

Es wird schwierig sein, die Datenbank zu ändern, um diese Struktur zu verwenden, ohne bestehende Anwendungen zu unterbrechen.

    
Mark Byers 01.07.2010 12:36
quelle
1

Nur weil keine normalen Regeln gebrochen sind, bedeutet das nicht, dass es kein schlechtes Datenbankdesign ist. Im Allgemeinen ist es besser, wenn Sie ein Design mit kleineren, dichter gepackten Zeilen verwenden, da auf diese Weise mehr Zeilen in eine Seite passen, sodass die Datenbank weniger Arbeit benötigt. Mit dem aktuellen Design muss der Datenbankserver viel Platz für die Speicherung von Nullwerten aufwenden.

Das Vermeiden von bestehenden Anwendungen ist der schwierigste Teil. Wenn die anderen Anwendungen nur Lesezugriff benötigen, können Sie eine Ansicht schreiben, die mit der alten Tabelle identisch aussieht.

    
Nathan Hughes 01.07.2010 12:38
quelle
1

Wenn Sie Ihre Tabellenstruktur ändern, würde ich eine Ansicht mit dem Namen tblSampleData empfehlen, die die gleichen Daten zurückgibt wie die Tabelle jetzt. Das wird etwas Kompatibilität erhalten.

    
Jonathan 01.07.2010 12:53
quelle
1
  1. Sie benötigen wahrscheinlich nicht einmal ein RDBMS für diese Daten . Speichern Sie Ihre Daten in strukturierten Binärdateien oder in einer DBM / ISAM-Tabelle.

  2. Es ist nicht normalisiert. In der Regel ist der Mangel an Normalisierung die Ursache all Ihrer Probleme. Aber in diesem Fall ist das Fehlen der Normalisierung nicht das Ende der Welt, denn diese Daten sind "nur lesbar" , es gibt nur einen Schlüssel, und es ist nicht mit etwas anderem verbunden. Update-Anomalien sollten also keine Sorge sein. Sie müssen sich nur sorgen, dass die Originaldaten konsistent sind.

  3. Mit all diesen NULL-Werten ist nichts zu fürchterlich falsch, wenn Sie NULL-Werte als "speziellen Wert" mit derselben Bedeutung für die gesamte App behandeln. Daten wurden nicht gesammelt. Keine Daten verfügbar. Subject weigerte sich, die Frage zu beantworten. Daten sind Ausreißer. Daten stehen aus. Es ist bekannt, dass Daten UNBEKANNT sind. Thema sagte, dass sie nicht wussten ... etc. Sie erhalten die Idee. Das Zulassen von NULL für keinen definierten Grund ohne definierte Bedeutung ist furchtbar falsch.

  4. Ich sage es normalisieren. Definieren Sie entweder spezielle Werte und erstellen Sie eine massive Tabelle. Oder lassen Sie NULL für die VB- und PHP-Programmierer, und teilen Sie Ihre Daten richtig auf. Erstellen Sie eine Ansicht, um die Datensicherung zu unterstützen, wenn Sie älteren Code unterstützen müssen. Von dem, was du beschrieben hast, sprichst du von ein paar Stunden Arbeit, um dieses Ding zu korrigieren. Das ist kein so schlechtes Geschäft.

John 01.07.2010 13:36
quelle
0

Nehmen wir an, Sie haben eine Testmaschine X mit 40 Messkanälen. Wenn Sie wissen, dass die Tester bei jedem Test nur ein paar Kanäle verwenden, können Sie das Design folgendermaßen ändern:

tblTest: testId, testDate tblResult: testId, machineId, channelId, Ergebnis

Sie können das vorherige Layout immer mithilfe einer Kreuztabelle abrufen.

    
Patrick Honorez 01.07.2010 13:06
quelle
0

Ich gehe mit 1 Haupttabelle, wo Sie 1 Reihe pro Probe haben würden, würde es alle Spalten enthalten, die jede Probe haben sollte:

%Vor%

Ich würde dann eine Tabelle für jeden anderen Test oder "Klasse" ähnlicher Tests hinzufügen und alle damit verbundenen Spalten einschließen (verwende den tatsächlichen Testnamen und nicht XYZ):

%Vor%

Wenn Sie nach einem Ergebnis suchen, suchen Sie in der Tabelle der Testmethoden, die angewendet wird, und verbinden Sie sie mit der tatsächlichen Beispieltabelle.

    
KM. 01.07.2010 13:02
quelle
0

EAV ist eine Option, aber die Abfragen werden Sie töten.

Ist es eine Option, die Daten wie MongoDB in eine NoSQL DB zu migrieren? Ich glaube, dass dies der effizienteste und einfachste Weg für Ihr Problem sein wird. Da Sie erwähnt haben, dass Sie grundsätzlich CRUD-Abfragen durchführen, sollte NoSQL ziemlich effizient sein.

    
Alix Axel 01.07.2010 13:09
quelle
0

Das derzeitige Design ist schlecht. Im Allgemeinen ist eine Datenbank mit vielen NULL-Werten ein Hinweis auf ein schlechtes Design, das die 4. Normalform verletzt. Aber das größte Problem mit dem Design ist nicht eine Verletzung der normalen Prinzipien, sondern die Tatsache, dass das Hinzufügen eines neuen Testtyps Änderungen an der Datenbank Struktur erfordert, anstatt einfach einige Daten zu mehreren Tabellen, die einen Test "definieren". Schlimmer noch, es erfordert strukturelle Änderungen an einer bestehenden Tabelle, anstatt neue Tabellen hinzuzufügen.

Sie können die perfekte vierte Normalform erreichen, indem Sie ein Schlüssel-Wert-System wie von anderen beschrieben anpassen. Sie können jedoch das Design der Datenbank erheblich verbessern und trotzdem Ihre geistige Gesundheit bewahren (was bei der Arbeit mit Schlüsselwertsystemen ohne ORM schwer zu tun ist), indem Sie eine der folgenden Maßnahmen ergreifen:

  1. Es wurde versucht, die größte Anzahl von Messungen zu ermitteln, die zur Darstellung eines einzelnen Tests erforderlich sind. Wenn verschiedene Datentypen von den Tests zurückgegeben werden, müssen Sie die größte Anzahl von Werten jedes Datentyps ermitteln, die vom größten Test zurückgegeben werden. Erstellen Sie eine Tabelle mit nur diesen Spalten mit den Bezeichnungen Meas1, Meas2 usw. Anstelle von 400 Spalten benötigen Sie vielleicht 10. Oder 40. Erstellen Sie dann eine Reihe von Tabellen, die beschreiben, was jede Spalte für jeden Test bedeutet. Diese Informationen können verwendet werden, um aussagekräftige Eingabeaufforderungen bereitzustellen und Spaltenüberschriften in Abhängigkeit vom Typ des gespeicherten Tests zu melden. Dies wird NULLs nicht vollständig eliminieren, wird sie aber stark reduzieren. Solange ein neuer Test in die von Ihnen angegebene Anzahl von Messungen "passen" kann, können neue Tests als Daten und nicht als strukturelle Änderungen hinzugefügt werden.

  2. Ermitteln Sie die tatsächliche Liste der Messungen für jeden Test und erstellen Sie eine separate Tabelle für die Ergebnisse der einzelnen Tests (grundlegende Informationen wie die Test-ID, wer sie lief, die Zeit usw. gehen immer noch in eine einzige Tabelle). Dies ist ein Vererbungsmuster mit mehreren Tabellen (ich weiß nicht, ob es einen echten Namen hat). Sie müssen immer noch eine neue "Daten" -Tabelle für jeden neuen Test erstellen, aber jetzt werden Sie keine anderen vorhandenen Produktionstabellen berühren und Sie werden in der Lage sein, eine perfekte Normalform zu erreichen.

Ich hoffe, dies bietet einige Ideen, um loszulegen.

    
Larry Lustig 01.07.2010 13:26
quelle