it-swarm.com.de

Warum sollten wir keine NULL zulassen?

Ich erinnere mich, dass ich diesen einen Artikel über Datenbankdesign gelesen habe, und ich erinnere mich auch, dass gesagt wurde, Sie sollten Feldeigenschaften von NOT NULL haben. Ich erinnere mich nicht, warum dies der Fall war.

Ich kann mir nur vorstellen, dass Sie als Anwendungsentwickler nicht auf NULL nd einen möglichen nicht vorhandenen Datenwert testen müssen (z. B. eine leere Zeichenfolge für Zeichenfolgen).

Aber was machen Sie bei Datum, Uhrzeit und Uhrzeit (SQL Server 2008)? Sie müssten ein historisches oder ein Bottom-out-Datum verwenden.

Irgendwelche Ideen dazu?

127
Thomas Stringer

Ich denke, die Frage ist schlecht formuliert, da der Wortlaut impliziert, dass Sie bereits entschieden haben, dass NULL schlecht sind. Vielleicht meinten Sie "Sollen wir NULL zulassen?"

Wie auch immer, hier ist meine Meinung dazu: Ich denke, NULL-Werte sind eine gute Sache. Wenn Sie anfangen, NULL-Werte zu verhindern, nur weil "NULL-Werte schlecht" oder "NULL-Werte sind schwer", beginnen Sie, Daten zu erstellen. Was ist zum Beispiel, wenn Sie mein Geburtsdatum nicht kennen? Was wirst du in die Spalte setzen, bis du es weißt? Wenn Sie so etwas wie viele Anti-NULL-Leute sind, geben Sie 1900-01-01 ein. Jetzt werde ich in die Geriatrie eingeliefert und bekomme wahrscheinlich einen Anruf von meinem lokalen Nachrichtensender, der mir zu meinem langen Leben gratuliert und mich nach meinen Geheimnissen für ein so langes Leben usw. fragt.

Wenn eine Zeile eingegeben werden kann, in der es möglich ist, dass Sie den Wert einer Spalte nicht kennen , denke ich NULL Es ist viel sinnvoller, als einen beliebigen Token-Wert auszuwählen, um die Tatsache darzustellen, dass er unbekannt ist - ein Wert, den andere bereits kennen, zurückentwickeln oder nachfragen müssen, um herauszufinden, was er bedeutet.

Es gibt jedoch ein Gleichgewicht - nicht jede Spalte in Ihrem Datenmodell sollte nullwertfähig sein. In einem Formular befinden sich häufig optionale Felder oder Informationen, die zum Zeitpunkt der Erstellung der Zeile sonst nicht erfasst werden. Dies bedeutet jedoch nicht, dass Sie das Auffüllen aller Daten verschieben können. :-)

Auch die Fähigkeit, NULL zu verwenden, kann durch entscheidende Anforderungen im wirklichen Leben eingeschränkt werden. Im medizinischen Bereich kann es beispielsweise eine Frage von Leben oder Tod sein, zu wissen , warum ein Wert unbekannt ist. Ist die Herzfrequenz NULL, weil es keinen Puls gab oder weil wir sie noch nicht gemessen haben? Können wir in einem solchen Fall NULL in die Herzfrequenzspalte einfügen und Notizen oder eine andere Spalte mit einem NULL-weil-Grund haben?

Haben Sie keine Angst vor NULL-Werten, sondern lernen oder diktieren Sie, wann und wo sie verwendet werden sollen und wann und wo sie nicht verwendet werden sollen.

232
Aaron Bertrand

Festgestellte Gründe sind:

  • NULL ist kein Wert und hat daher keinen intrinsischen Datentyp. Nullen benötigen überall eine spezielle Behandlung , wenn Code, der sich ansonsten auf tatsächliche Typen stützt, möglicherweise auch den nicht typisierten NULL-Wert erhält.

  • NULL unterbricht die Zwei-Wert-Logik (bekannt als Wahr oder Falsch) und erfordert eine Drei-Wert-Logik. Die korrekte Implementierung ist weitaus komplexer und wird von den meisten Datenbankadministratoren und nahezu allen Nicht-Datenbankadministratoren mit Sicherheit nur unzureichend verstanden. Infolgedessen lädt es positiv viele subtile Fehler in die Anwendung ein.

  • Die semantische Bedeutung eines bestimmten NULL bleibt im Gegensatz zu tatsächlichen Werten der Anwendung überlassen.

    Semantik wie "nicht anwendbar" und "unbekannt" und "Sentinel" sind üblich, und es gibt auch andere. Sie werden häufig gleichzeitig in derselben Datenbank verwendet, auch innerhalb derselben Beziehung. und sind natürlich unerklärliche und nicht unterscheidbare und inkompatible Bedeutungen.

  • Sie sind für relationale Datenbanken nicht erforderlich, wie in „Umgang mit fehlenden Informationen ohne Nullen“ dargelegt. Eine weitere Normalisierung ist ein offensichtlicher erster Schritt, um eine Tabelle mit NULL-Werten zu entfernen.

Dies bedeutet nicht, dass NULL niemals erlaubt sein sollte. Es tut argumentieren, dass es viele gute Gründe gibt, NULL zu verbieten, wo immer dies möglich ist.

Bezeichnenderweise spricht es dafür, sich sehr zu bemühen - durch ein besseres Schemadesign, bessere Datenbank-Engines und noch bessere Datenbanksprachen -, make NULL häufiger zu vermeiden.

Fabian Pascal antwortet auf eine Reihe von Argumenten in "Nulls Nullified" .

61
bignose

Ich bin anderer Meinung, Nullen sind ein wesentliches Element des Datenbankdesigns. Die Alternative wäre, wie Sie ebenfalls angedeutet haben, eine Verbreitung bekannter Werte, um das Fehlende oder Unbekannte darzustellen. Das Problem liegt darin, dass Null so häufig missverstanden und infolgedessen unangemessen verwendet wird.

IIRC, Codd schlug vor, die derzeitige Implementierung von Null (dh nicht vorhanden/fehlend) zu verbessern, indem zwei Nullmarker anstelle von einem "nicht vorhanden, aber anwendbar" und "nicht vorhanden und nicht anwendbar" verwendet werden. Ich kann mir nicht vorstellen, wie relationale Designs dadurch persönlich verbessert würden.

32

Lassen Sie mich zunächst sagen, dass ich kein DBA bin, sondern auswendig Entwickler bin und unsere Datenbanken entsprechend unseren Anforderungen pflege und aktualisiere. Davon abgesehen hatte ich aus mehreren Gründen die gleiche Frage.

  1. Nullwerte erschweren die Entwicklung und sind fehleranfällig.
  2. Nullwerte machen Abfragen, gespeicherte Prozeduren und Ansichten komplexer und fehleranfälliger.
  3. Nullwerte belegen Speicherplatz (? Bytes basierend auf fester Spaltenlänge oder 2 Bytes für variable Spaltenlänge).
  4. Nullwerte können und werden häufig die Indizierung und Mathematik beeinflussen.

Ich verbringe sehr viel Zeit damit, die vielen Antworten, Kommentare, Artikel und Ratschläge im Internet zu sichten. Unnötig zu erwähnen, dass die meisten Informationen in etwa der Antwort von @ AaronBertrand entsprachen. Deshalb hatte ich das Bedürfnis, auf diese Frage zu antworten.

Erstens möchte ich für alle zukünftigen Leser etwas klarstellen ... NULL-Werte repräsentieren unbekannte Daten, NICHT unbenutzte Daten. Wenn Sie eine Mitarbeitertabelle mit einem Feld für das Kündigungsdatum haben. Ein Nullwert am Kündigungsdatum ist, weil es sich um ein zukünftig erforderliches Feld handelt, das derzeit unbekannt ist. Jedem aktiven oder gekündigten Mitarbeiter wird irgendwann ein Datum in dieses Feld eingefügt. Das ist meiner Meinung nach der einzige Grund für ein Nullable-Feld.

Davon abgesehen würde dieselbe Mitarbeitertabelle höchstwahrscheinlich eine Art von Authentifizierungsdaten enthalten. In einer Unternehmensumgebung werden Mitarbeiter häufig in der Datenbank für Personal und Buchhaltung aufgeführt, haben jedoch nicht immer Authentifizierungsdetails oder benötigen diese. Die meisten Antworten lassen Sie glauben, dass es in Ordnung ist, diese Felder auf Null zu setzen oder in einigen Fällen ein Konto für sie zu erstellen, ihnen jedoch niemals die Anmeldeinformationen zu senden. Ersteres veranlasst Ihr Entwicklungsteam, Code zu schreiben, um nach NULL-Werten zu suchen und entsprechend damit umzugehen, und letzteres birgt ein großes Sicherheitsrisiko! Konten, die noch nie im System verwendet werden, erhöhen nur die Anzahl der möglichen Zugriffspunkte für einen Hacker und belegen wertvollen Datenbankspeicher für etwas, das nie verwendet wird.

In Anbetracht der obigen Informationen besteht der beste Weg, mit nullbaren Daten umzugehen, die verwendet werden, darin, nullbare Werte zuzulassen. Es ist traurig, aber wahr und Ihre Entwickler werden Sie dafür hassen. Der zweite Typ von nullbaren Daten sollte in eine verwandte Tabelle (IE: Konto, Anmeldeinformationen usw.) gestellt werden und eine Eins-zu-Eins-Beziehung haben. Auf diese Weise kann ein Benutzer ohne Anmeldeinformationen existieren, sofern diese nicht benötigt werden. Dies beseitigt das zusätzliche Sicherheitsrisiko, wertvollen Datenbankspeicher und sorgt für eine viel sauberere Datenbank.

Unten finden Sie eine sehr vereinfachte Tabellenstruktur, die sowohl die erforderliche nullfähige Spalte als auch eine Eins-zu-Eins-Beziehung zeigt.

Unknown Nullable and One-to-One relationship

Ich weiß, dass ich etwas spät zur Party komme, seit diese Frage vor Jahren gestellt wurde, aber hoffentlich hilft dies, etwas Licht in dieses Thema zu bringen und wie man am besten damit umgeht.

14

Abgesehen von all den Problemen mit NULL verwirrenden Entwicklern haben NULL einen weiteren sehr schwerwiegenden Nachteil: die Leistung

NULL-fähige Spalten sind aus Sicht der Leistung eine Katastrophe. Betrachten Sie als Beispiel die Ganzzahlarithmetik. In einer vernünftigen Welt ohne NULL ist es "einfach", Ganzzahlarithmetik im Code der Datenbank-Engine mithilfe von SIMD-Anweisungen zu vektorisieren, um so ziemlich jede Berechnung mit Geschwindigkeiten durchzuführen, die schneller als 1 Zeile pro CPU-Zyklus sind. In dem Moment, in dem Sie NULL einführen, müssen Sie jedoch alle von NULL erstellten Sonderfälle behandeln. Moderne CPU-Befehlssätze (lesen Sie: x86/x64/ARM und GPU-Logik auch) sind einfach nicht dafür ausgestattet.

Betrachten Sie die Teilung als Beispiel. Auf einer sehr hohen Ebene ist dies die Logik, die Sie mit einer Ganzzahl ungleich Null benötigen:

if (b == 0)
  do something when dividing by error
else
  return a / b

Mit NULL wird dies etwas schwieriger. Zusammen mit b benötigen Sie einen Indikator, wenn b null ist, und ähnlich für a. Der Scheck wird jetzt:

if (b_null_bit == NULL)
   return NULL
else if (b == 0) 
   do something when dividing by error
else if (a_null_bit == NULL)
   return NULL
else 
   return a / b

Die NULL-Arithmetik läuft auf einer modernen CPU erheblich langsamer als die Nicht-Null-Arithmetik (um den Faktor 2-3x).

Es wird schlimmer, wenn Sie SIMD einführen. Mit SIMD kann eine moderne Intel-CPU 4 x 32-Bit-Ganzzahldivisionen in einem einzigen Befehl wie folgt ausführen:

x_vector = a_vector / b_vector
if (fetestexception(FE_DIVBYZERO))
   do something when dividing by zero
return x_vector;

Jetzt gibt es auch im SIMD-Land Möglichkeiten, mit NULL umzugehen. Dazu müssen jedoch mehr Vektoren und CPU-Register verwendet und eine clevere Bitmaskierung durchgeführt werden. Selbst mit guten Tricks schleicht sich der Leistungsverlust der NULL-Ganzzahlarithmetik für relativ einfache Ausdrücke in den 5-10-fach langsameren Bereich.

So etwas gilt für Aggregate und in gewissem Maße auch für Joins.

Mit anderen Worten: Die Existenz von NULL in SQL ist eine Impedanzfehlanpassung zwischen der Datenbanktheorie und dem tatsächlichen Design moderner Computer. Es gibt einen ziemlich guten Grund, warum NULL Entwickler verwirrt - weil eine Ganzzahl in den meisten vernünftigen Programmiersprachen nicht NULL sein kann -, so funktionieren Computer einfach nicht.

13
Thomas Kejser

Wikipedia-Artikel zu SQL Null enthält einige interessante Anmerkungen zum NULL-Wert und als datenbankunabhängige Antwort, sofern Sie sich der möglichen Auswirkungen von NULL-Werten für Ihr spezifisches RDBMS bewusst sind akzeptabel in Ihrem Design. Andernfalls könnten Sie Spalten nicht als nullwert angeben.

Beachten Sie nur, wie Ihr RDBMS sie in SELECT-Operationen wie Mathematik und auch in Indizes behandelt.

10
Derek Downey

Interessante Fragen.

Ich kann mir nur vorstellen, dass Sie als Anwendungsentwickler nicht auf NULL und einen möglichen nicht vorhandenen Datenwert (z. B. eine leere Zeichenfolge für Zeichenfolgen) testen müssen.

Es ist komplizierter als das. Null hat eine Reihe unterschiedlicher Bedeutungen und ein wirklich wichtiger Grund, Nullen in vielen Spalten nicht zuzulassen, ist, dass wenn die Spalte Null ist, dies nur eine Sache bedeutet (nämlich, dass sie nicht in einem äußeren Join angezeigt wurde). Darüber hinaus können Sie Mindeststandards für die Dateneingabe festlegen, was sehr hilfreich ist.

Aber was machen Sie bei Datum, Uhrzeit und Uhrzeit (SQL Server 2008)? Sie müssten ein historisches oder ein Bottom-out-Datum verwenden.

Dies zeigt sofort ein Problem mit Nullen, nämlich dass ein in einer Tabelle gespeicherter Wert entweder "dieser Wert gilt nicht" oder "wir wissen es nicht" bedeuten kann. Bei Zeichenfolgen kann eine leere Zeichenfolge als "dies gilt nicht" dienen. Bei Datums- und Uhrzeitangaben gibt es jedoch keine solche Konvention, da es keinen gültigen Wert gibt, der dies herkömmlicherweise bedeutet. Normalerweise stecken Sie dort mit NULL-Werten fest.

Es gibt Möglichkeiten, dies zu umgehen (indem Sie mehr Beziehungen hinzufügen und verbinden), aber diese stellen genau die gleichen semantischen Klarheitsprobleme dar wie NULL-Werte in der Datenbank. Für diese Datenbanken würde ich mir darüber keine Sorgen machen. Es gibt einfach nichts, was Sie wirklich dagegen tun können.

BEARBEITEN: Ein Bereich, in dem NULL are unverzichtbar ist, sind Fremdschlüssel. Hier haben sie normalerweise nur eine Bedeutung, die mit der Null in der äußeren Verknüpfungsbedeutung identisch ist. Dies ist natürlich eine Ausnahme vom Problem.

10
Chris Travers