Warum sollten wir keine NULL-Werte zulassen?

125

Ich erinnere mich, dass ich diesen einen Artikel über das Datenbankdesign gelesen habe, und ich erinnere mich auch, dass gesagt wurde, Sie sollten Feldeigenschaften von NOT NULL haben. Ich weiß nicht mehr, warum das so war.

Alles, woran ich denken kann, ist, dass Sie als Anwendungsentwickler nicht auf NULL und einen möglicherweise nicht vorhandenen Datenwert (z. B. eine leere Zeichenfolge für Zeichenfolgen) testen müssen .

Was tun Sie bei Datum, Uhrzeit und Datum (SQL Server 2008)? Sie müssten ein historisches Datum oder ein Datum mit Talsohle verwenden.

Irgendwelche Ideen dazu?

Thomas Stringer
quelle
4
Diese Antwort bietet einen Einblick in die Verwendung von NULL. Dba.stackexchange.com/questions/5176/…
Derek Downey
10
"Ja wirklich?" Warum können wir mit RDBMS überhaupt NULL verwenden, wenn wir sie nicht verwenden sollten? An NULL ist nichts auszusetzen, solange Sie wissen, wie Sie damit umgehen sollen.
Fr0zenFyr
3
War dies eine BI-Datenmodellierung? Sie sollten im Allgemeinen keine Nullen in Faktentabellen zulassen. Andernfalls sind Nullen Ihre Freunde, wenn sie ordnungsgemäß verwendet werden. =)
sam yi
2
@ Fr0zenFyr, nur weil ein RDBMS es uns ermöglicht, etwas zu tun, ist es nicht unbedingt eine gute Idee, dies zu tun. Nichts zwingt uns, einen Primärschlüssel oder einen eindeutigen Schlüssel in einer Tabelle zu deklarieren, aber mit wenigen Ausnahmen tun wir es trotzdem.
Lennart
3
Ich denke, eine vollständige Behandlung dieses Themas müsste auf Codds ursprüngliche Anforderung verweisen, dass ein RDBMS eine systematische Methode zur Behandlung fehlender Daten haben muss. In der realen Welt gibt es Situationen, in denen ein Speicherort für Daten erstellt wird, in dem jedoch keine Daten gespeichert werden müssen. Der Datenarchitekt muss eine Antwort darauf finden, unabhängig davon, ob es sich um Datenbankdesign, Anwendungsprogrammierung oder beides handelt. Der SQL-NULL-Wert ist nicht perfekt, um diese Anforderung zu erfüllen, aber er ist besser als gar nichts.
Walter Mitty

Antworten:

230

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

Wie auch immer, hier ist meine Sichtweise: Ich denke, NULLs sind eine gute Sache. Wenn Sie NULLs verhindern, nur weil "NULLs sind schlecht" oder "NULLs sind hart", beginnen Sie, Daten zu erstellen. Was ist zum Beispiel, wenn Sie mein Geburtsdatum nicht kennen? Was werden Sie in die Spalte setzen, bis Sie wissen? Wenn Sie so etwas wie Anti-NULL-Leute sind, geben Sie 1900-01-01 ein. Jetzt werde ich in die Geriatrie eingewiesen und wahrscheinlich einen Anruf von meinem lokalen Nachrichtensender erhalten.

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

Es besteht jedoch ein Gleichgewicht - nicht jede Spalte in Ihrem Datenmodell sollte nullwertfähig sein. Es gibt häufig optionale Felder in einem Formular oder Informationen, die ansonsten zum Zeitpunkt der Erstellung der Zeile 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 sein. Im medizinischen Bereich kann es beispielsweise lebenswichtig sein, zu wissen, warum ein Wert unbekannt ist. Ist die Herzfrequenz NULL, weil es keinen Puls gab oder weil wir ihn noch nicht gemessen haben? Können wir in einem solchen Fall NULL in die Herzfrequenzspalte setzen und Notizen oder eine andere Spalte mit einem NULL-Grund haben?

Haben Sie keine Angst vor Nullen, sondern sind Sie bereit zu lernen oder zu diktieren, wann und wo sie verwendet werden sollen und wann und wo nicht.

Aaron Bertrand
quelle
3
"Ein willkürlicher Token-Wert, der die Tatsache repräsentiert, dass er unbekannt ist", wird als Sentinel-Wert bezeichnet
Alexander
4
Aber was hindert Sie daran, eine separate Tabelle zu erstellen, birth_datein der Sie Geburtsdaten speichern? Wenn das Geburtsdatum unbekannt ist, geben Sie einfach kein Geburtsdatum in ein birth_date. Nullen sind eine Katastrophe.
Eldar Agalarov
6
@EldarAgalarov Das klingt nach Trumps Argumentation („Katastrophe“ warum? Wie? Für wen? Ihre Meinung, dass etwas eine „Katastrophe“ ist, macht es nicht so). Wie auch immer, das Geburtsdatum ist nur ein Beispiel. Wenn Sie Personal, Mitglieder oder Kunden mit 15 potenziell nullwertfähigen Spalten haben, werden Sie 15 sekundäre Tabellen erstellen? Was ist, wenn Sie 50 haben? Was passiert, wenn Ihre DW-Faktentabelle 500 enthält? Die Wartung, um große, unheimliche NULL-Werte aus Ihrer Datenbank fernzuhalten, wird 10x so schlimm wie jede „Katastrophe“, vor der Sie Angst haben ...
Aaron Bertrand
3
@AaronBertrand Wenn Ihre Tabelle 15 potenziell nullfähige Spalten enthält, riecht es wirklich schlecht ^^ Nicht, dass eine große Anzahl von Spalten von Natur aus schlecht ist, aber dies kann auf ein schlechtes Design oder eine erforderliche Denormalisierung hinweisen. Aber es wird Fragen aufwerfen.
programaths
2
@Wildcard Sie haben also noch nie einen Laden gesehen 1900-01-01, um einen NULL-Wert für Datum und Uhrzeit zu vermeiden? OK dann. Auch NULL = unbekannt und unbekannt = falsch. Ich bin mir nicht sicher, welche Probleme dies verursachen könnte, außer dass Menschen nicht mit diesem Wissen geboren werden (als ob sie nicht mit vielen Dingen geboren würden, die einem komplexen RDBMS inhärent sind). Wieder winkte er mit den Händen und sagte: "Problem! Katastrophe!" macht es nicht so.
Aaron Bertrand
57

Gründe dafür sind:

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

  • NULL bricht die Zwei-Wert-Logik (vertrautes Wahr oder Falsch) und erfordert eine Drei-Wert-Logik. Die korrekte Implementierung ist weitaus komplexer und wird von den meisten Datenbankadministratoren und fast allen Nicht-Datenbankadministratoren nur schlecht verstanden. Infolgedessen werden viele subtile Fehler in der Anwendung positiv hervorgerufen .

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

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

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

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

Bezeichnenderweise argumentiert es sehr schwer für den Versuch - durch eine bessere Schema - Design und eine bessere Datenbank - Engines, und eine noch bessere Datenbanksprachen - machen es möglich , NULL oft mehr zu vermeiden.

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

große Nase
quelle
3
Ihr Link zu "Umgang mit fehlenden Informationen ohne Nullen" zeigt recht gut, warum wir nicht ohne Nullen auskommen können: Einige der Vorschläge könnten in den gängigen RDBMSs, wie sie derzeit vorliegen, nicht auf rationale Weise umgesetzt werden.
Jack Douglas
7
Jack: Richtig, aber "die aktuellen Implementierungen können es nicht" ist kein Argument für den Status quo :-)
großartig
17
Heißt das, wir sollten nicht fliegen, weil Flugzeuge nicht perfekt sind?
Aaron Bertrand
11
Nein, es heißt, dass die Anbieter keine Entschuldigungen für Nullen mehr geltend machen sollten, die möglicherweise vor vierzig Jahren gültig waren, aber ihre angemessene Aufbewahrungsfrist schon lange überschritten haben. Die E / A-Zeiten liegen nicht mehr in der Größenordnung von 80 ms. Einzelne CPU-Zyklen liegen nicht mehr in der Größenordnung von Mikrosekunden. Speichergrenzen liegen nicht mehr in der Größenordnung einiger Megabytes. Anders als vor vierzig Jahren gibt es jetzt die Hardwaregeschwindigkeiten und -kapazitäten, die für das Arbeiten ohne Nullen erforderlich sind, wobei die Kosten nicht unerschwinglich sind. Er sagt, es ist Zeit weiterzumachen.
Erwin Smout
2
Der Link "NULL confusion" ist nicht mehr aktiv.
jpmc26
32

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

Das IIRC, Codd, schlug vor, die derzeitige Implementierung von Null (dh nicht vorhanden / nicht vorhanden) zu verbessern, indem zwei Nullmarkierungen anstelle einer "nicht vorhanden, aber anwendbar" und "nicht vorhanden und nicht anwendbar" verwendet werden. Ich kann mir nicht vorstellen, wie sich relationale Designs dadurch persönlich verbessern lassen.

Mark Storey-Smith
quelle
2
Ich schlage vor, einen benutzerdefinierten Satz verschiedener Arten von nullund eine benutzerdefinierte mehrwertige Logik zu verwenden: p
Jack Douglas
13
Das sind nicht die einzigen Möglichkeiten. Sie schließen die Normalisierungsalternative aus: Verwenden Sie anstelle von Spalten, die einen Wert haben können oder nicht, eine andere Tabelle, die eine entsprechende Zeile für die erste Tabelle haben kann oder nicht. Die Bedeutung des Vorhandenseins oder Nichtvorhandenseins einer Zeile ergibt sich aus der Bedeutung der Tabellen, und es gibt keine spezielle
Schreibweise für NULL-
7
Das Vorhandensein von NULL erfordert keine Sonder- oder Sentinel-Werte. Dies sind nur Symptome dafür, wie manche Leute sich entscheiden, mit NULL umzugehen.
Aaron Bertrand
Es ist erwähnenswert, dass '' in PostgreSQL (wenn auch nicht in Oracle) von null verschieden ist und Ihnen so eine zweifache Markierung gibt, und Sie könnten 0 für numerische Spalten verwenden. Das Problem mit 0 ist jedoch, dass es für Fremdschlüssel nicht funktioniert.
Chris Travers
13

Lassen Sie mich zunächst sagen, ich bin kein DBA, ich bin auswendig ein Entwickler und ich pflege und aktualisiere unsere Datenbanken basierend auf unseren Bedürfnissen. Davon abgesehen hatte ich aus ein paar 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 Platz (? Bytes basierend auf fester Spaltenlänge oder 2 Bytes für variable Spaltenlänge).
  4. Nullwerte können und beeinflussen häufig die Indizierung und die Mathematik.

Ich verbringe sehr viel Zeit damit, die zahlreichen Antworten, Kommentare, Artikel und Ratschläge im Internet zu durchsuchen. Es erübrigt sich zu erwähnen, dass die meisten Informationen in etwa der Antwort von @ AaronBertrand entsprachen. Aus diesem Grund hatte ich das Bedürfnis, auf diese Frage zu antworten.

Zunächst möchte ich etwas klarstellen für alle zukünftigen Leser ... NULL-Werte stehen für unbekannte Daten, NICHT für unbenutzte Daten. Wenn Sie eine Mitarbeitertabelle mit einem Kündigungsdatum haben. Ein Nullwert für das Beendigungsdatum ist ein zukünftig erforderliches Feld, das derzeit nicht bekannt ist. Jedem aktiven oder gekündigten Mitarbeiter wird irgendwann ein Datum hinzugefügt. Das ist meiner Meinung nach der einzige Grund für ein Nullable-Feld.

Davon abgesehen würde dieselbe Mitarbeitertabelle höchstwahrscheinlich eine Art Authentifizierungsdaten enthalten. In einer Unternehmensumgebung ist es üblich, dass Mitarbeiter in der Datenbank für Personalwesen und Buchhaltung aufgeführt werden, jedoch nicht immer über Authentifizierungsdetails verfügen oder diese benötigen. Die meisten Antworten lassen Sie glauben, dass es in Ordnung ist, diese Felder zu löschen oder in einigen Fällen ein Konto für sie zu erstellen, aber niemals die Anmeldeinformationen an sie zu senden. Ersteres veranlasst Ihr Entwicklungsteam, Code zu schreiben, um auf NULL-Werte zu prüfen und entsprechend damit umzugehen, und letzteres birgt ein enormes Sicherheitsrisiko! Konten, die noch nie im System verwendet werden, erhöhen nur die Anzahl der möglichen Zugriffspunkte für einen Hacker. Außerdem belegen sie wertvollen Datenbankspeicherplatz für etwas, das noch nie verwendet wird.

Angesichts der obigen Informationen ist die beste Möglichkeit, mit nullwertfähigen Daten umzugehen, die verwendet werden, nullwertfähige Werte zuzulassen. Es ist traurig, aber wahr, und Ihre Entwickler werden Sie dafür hassen. Der zweite Typ von nullwertfähigen Daten sollte in eine verwandte Tabelle gestellt werden (IE: Konto, Anmeldeinformationen usw.) 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 und wertvollen Datenbankspeicher und sorgt für eine viel sauberere Datenbank.

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

Unbekannte Nullable- und One-to-One-Beziehung

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

Nicholas Aguirre
quelle
2
Ich würde es nur so ändern, dass es keine TerminationDatein den Mitarbeiterdatensätzen gibt, sondern eine Tabelle, für TerminatedEmployeedie Mitarbeiter von der Anwendung verschoben (nicht kopiert) werden, wenn sie beendet werden. Offensichtlich funktioniert dies sehr gut mit der Account-Tabelle, da keine verknüpften Accounts in der TerminatedEmployeeTabelle vorhanden sind. Wenn Sie die Telefonnummern weiterhin benötigen, würde ich die Fremdschlüssel umkehren, sodass die Mitarbeiter- und die gekündigten Mitarbeiter-Tabellen die ID der Telefonnummer enthalten und nicht umgekehrt.
Programster
2
Ich könnte buchstäblich tagelang darüber nachdenken, warum dies schlecht sein würde. Redundante Tabellen, schlechte SQL-Praktiken, sodass Ihre Entwickler an zwei Stellen nach Mitarbeiterdaten, Problemen mit der Berichterstellung, Problemen mit direkten URIs für einen Mitarbeiter suchen müssen, der nicht vorhanden ist (verschoben wurde), und die Liste wird fortgesetzt und weiter. Es ist völlig in Ordnung, NULL für Felder zu haben, die irgendwann einen Wert haben werden. Es ist eine andere Geschichte, Felder zu haben, die niemals gefüllt werden und niemals eine Verwendung haben. Eine Reihe von potenziellen Problemen und Problemumgehungen, die diese Arbeit erleichtern könnten, wären das kleine Problem, in einem Feld nach NULL zu suchen, nicht wert.
Nicholas Aguirre
1
Ich stimme dir nicht zu. Das einzige redundante Element ist das Nullfeld für das Beendigungsdatum, das möglicherweise nie ausgefüllt wird. Entwickler müssen nur in der entsprechenden Tabelle nach den gewünschten Daten suchen und können die Leistung verbessern. Wenn Sie aus irgendeinem Grund sowohl gekündigte als auch nicht gekündigte Mitarbeiter haben möchten, wird dies durch einen Join behoben. In 90% der Fälle wird Ihre Anwendung jedoch wahrscheinlich den einen oder anderen Mitarbeiter benötigen. Ich denke, das Layout, das ich angegeben habe, ist besser, weil es unmöglich wäre, ein Kündigungsdatum für einen Mitarbeiter zu haben und für ihn noch ein Konto zu haben.
Programster
2
Ich sagte nicht redundante Daten, ich sagte redundante Tabellen. Darüber hinaus muss jede Änderung an den Mitarbeitertabellen auf die terminierten Tabellen übertragen werden. Dies macht die App fehleranfällig und macht die Arbeit des Entwicklers viel schwieriger. Außerdem wird ein Kündigungsdatum-Feld für fast alle ausgefüllt. Es ist verschwenderisch und problematisch, eine zweite identische Tabellenstruktur zu erstellen und auch Daten zu verschieben. Nicht jedes Mal das Testen einschließen, um sicherzustellen, dass die Tabellendaten verschoben und bereinigt wurden. Es ist eine schlechte Praxis, Daten aus einer Tabelle zu entfernen, selbst wenn sie nur verschoben werden sollen. Wenn Sie sich so für ein einzelnes Feld interessieren, dass ...
Nicholas Aguirre
1
... das wird fast immer rechtzeitig ausgefüllt und dann eine terminierte Tabelle mit einer 1-zu-1-Beziehung an den Mitarbeiter zurückgegeben. Ich arbeite sowohl als DBA als auch als Entwickler den ganzen Tag mit verschiedenen Datenbanken und bin froh, dass ich noch keine mit der von Ihnen vorgeschlagenen Struktur gefunden habe. Insbesondere aus der Sicht eines Entwicklers wäre es ein Albtraum, alles zu schreiben und Fehler zu überprüfen, da man nicht weiß, von welchem ​​Tisch es stammt. Selbst wenn Sie einen Join schreiben, enthalten die an die Software zurückgegebenen Daten ein Feld mit NULL-Daten, sodass Sie dies auch noch testen müssen.
Nicholas Aguirre
13

Abgesehen von all den Problemen mit verwirrenden NULL-Entwicklern haben NULL-Werte einen weiteren 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", Integer-Arithmetik im Datenbank-Engine-Code mithilfe von SIMD-Anweisungen zu vektorisieren, um so ziemlich jede Berechnung mit Geschwindigkeiten durchzuführen, die schneller als 1 Zeile pro CPU-Zyklus sind. Sobald Sie jedoch NULL einführen, müssen Sie alle Sonderfälle behandeln, die NULL erstellt. Moderne CPU-Befehlssätze (zu lesen: x86 / x64 / ARM und auch GPU-Logik) sind dafür einfach nicht effizient ausgestattet.

Betrachten Sie Division als Beispiel. Auf einer sehr hohen Ebene ist dies die Logik, die Sie für eine Ganzzahl ungleich Null benötigen:

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

Mit NULL wird dies etwas kniffliger. Zusammen mit bIhnen benötigen Sie einen Indikator, wenn bnull ist und ähnlich für a. Der Scheck wird nun:

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 ist auf einer modernen CPU wesentlich 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-Integer-Divisionen in einem einzigen Befehl ausführen:

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

Nun gibt es auch Möglichkeiten, mit NULL im SIMD-Land umzugehen, aber dies erfordert die Verwendung von mehr Vektoren und CPU-Registern und einige clevere Bitmaskierungen. Selbst mit guten Tricks schleicht sich der Performance-Nachteil der NULL-Ganzzahl-Arithmetik für relativ einfache Ausdrücke in den 5-10-fach langsameren Bereich.

So etwas gilt für Aggregate und zum Teil auch für Joins.

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

Thomas Kejser
quelle
10

Interessante Fragen.

Alles, woran ich denken kann, ist, dass Sie als Anwendungsentwickler nicht auf NULL und einen möglicherweise nicht vorhandenen Datenwert (z. B. eine leere Zeichenfolge für Zeichenfolgen) testen müssen.

Es ist komplizierter als das. Null hat eine Reihe von unterschiedlichen Bedeutungen und ein wirklich wichtiger Grund, Nullen in vielen Spalten nicht zuzulassen, ist, dass, wenn die Spalte null ist, dies eine und nur eine Sache bedeutet (nämlich, dass sie nicht in einem Outer Join aufgetaucht ist). Außerdem können Sie Mindeststandards für die Dateneingabe festlegen, was sehr hilfreich ist.

Was tun Sie bei Datum, Uhrzeit und Datum (SQL Server 2008)? Sie müssten ein historisches Datum oder ein Datum mit Talsohle verwenden.

Das zeigt ein Problem mit Nullen auf Anhieb, 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, was dies üblicherweise bedeutet. In der Regel bleiben Sie dort mit NULL-Werten stecken.

Es gibt Möglichkeiten, dies zu umgehen (indem Sie mehr Relationen und Verknüpfungen hinzufügen), aber diese werfen genau dieselben semantischen Klarheitsprobleme auf 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.

EDIT: Ein Bereich , wo NULLs sind unverzichtbar in 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.

Chris Travers
quelle
10

Der Wikipedia-Artikel zu SQL Null enthält einige interessante Anmerkungen zum NULL-Wert. Als datenbankunabhängige Antwort können Sie NULL-Werte für Ihr spezifisches RDBMS verwenden, sofern Sie die möglichen Auswirkungen kennen. Wenn dies nicht der Fall wäre, könnten Sie Spalten nicht als nullfähig angeben.

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

Derek Downey
quelle
-12

Wow, die richtige Antwort "Lassen Sie keine NULL-Werte zu, wenn Sie das nicht müssen, weil sie die Leistung beeinträchtigen" ist irgendwie die zuletzt bewertete Antwort. Ich werde es unterstützen und ausarbeiten. Wenn ein RDBMS NULL für eine Spalte mit geringer Dichte zulässt, wird diese Spalte zu einer Bitmap hinzugefügt, in der nachverfolgt wird, ob der Wert für jede einzelne Zeile NULL ist. Wenn Sie also einer Spalte in einer Tabelle die NULL-Fähigkeit hinzufügen, in der alle Spalten keine NULL-Werte zulassen, erhöhen Sie den zum Speichern der Tabelle erforderlichen Speicherplatz. Außerdem muss das RDBMS die Bitmap lesen und darauf schreiben, was die Leistung bei allen Vorgängen beeinträchtigt.

In einigen Fällen kann das Zulassen von NULL 3NF unterbrechen. Stellen Sie sich das folgende Szenario vor, obwohl ich nicht wie viele meiner Kollegen ein Fan von 3NF bin:

In der Personentabelle gibt es eine Spalte mit dem Namen DateOfDeath, die auf Null gesetzt werden kann. Wenn eine Person gestorben ist, wird sie mit ihrem DateOfDeath ausgefüllt, andernfalls bleibt sie NULL. Es gibt auch eine nicht nullfähige Bitspalte mit dem Namen IsAlive. Diese Spalte wird auf 1 gesetzt, wenn die Person lebt, und auf 0, wenn die Person tot ist. Die überwiegende Mehrheit der gespeicherten Prozeduren verwendet die Spalte "IsAlive". Sie kümmern sich nur darum, ob eine Person am Leben ist, nicht um ihr DateOfDeath.

Die Spalte IsAlive unterbricht jedoch die Datenbanknormalisierung, da sie vollständig von DateOfDeath abgeleitet werden kann. Da IsAlive jedoch in den meisten SPs fest verdrahtet ist, besteht die einfache Lösung darin, DateOfDeath nicht auf Null zu setzen und der Spalte einen Standardwert zuzuweisen, falls die Person noch am Leben ist. Die wenigen SPs, die DateOfDeath verwenden, können dann umgeschrieben werden, um die IsAlive-Spalte zu überprüfen und das DateOfDeath nur dann zu berücksichtigen, wenn die Person nicht am Leben ist. Da sich die Mehrheit der SPs nur um IsAlive (ein bisschen) und nicht um DateOfDeath (ein Datum) kümmert, wird der Zugriff mit diesem Muster erheblich beschleunigt.

Ein nützliches T-SQL-Skript zum Auffinden nullbarer Spalten ohne NULL-Werte in allen Schemata ist:

select 'IF NOT EXISTS (SELECT 1 FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' WHERE ' + QUOTENAME(c.name) + ' IS NULL)
    AND (SELECT COUNT(*) FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ') > 1 PRINT ''' + s.name + '.' + t.name + '.' + REPLACE(c.name, '''', '''''') + ''''
    from sys.columns c
    inner join sys.tables t ON c.object_id = t.object_id
    inner join sys.schemas s ON s.schema_id = t.schema_id
    where c.is_nullable = 1 AND c.is_computed = 0
    order by s.name, t.name, c.name;

Wenn Sie dies auf einer Kopie Ihrer Produktionsdatenbank ausführen, finden Sie die Spaltenentwickler, die so markiert sind, dass sie NULL-Werte zulassen, die in der Praxis keine NULL-Werte haben. Die überwiegende Mehrheit von diesen kann als NOT NULL markiert werden, wodurch die Leistung erhöht und der Speicherplatz verringert wird.

Es ist möglicherweise nicht möglich, alle NULL-Werte in allen Tabellen zu entfernen, und das Design bleibt übersichtlich. Es ist jedoch von großem Vorteil, so viele NULL-Werte wie möglich zu entfernen. Der Optimierer arbeitet mit diesen Informationen viel schneller, und wenn Sie alle NULL-Werte in einer Tabelle entfernen können, können Sie beträchtlichen Speicherplatz zurückgewinnen.

Ich weiß, dass Datenbankadministratoren über Leistung nicht allzu viel nachdenken, aber Sie können nur eine begrenzte Menge an Arbeitsspeicher und Prozessorleistung in eine Lösung stecken, und irgendwann müssen Sie sich Gedanken über das logische und physische Design machen .

Beachten Sie auch, dass dies nur für echte RDBMS gilt und ich den technischen Teil meiner Antworten auf SQL Server beziehe. Das aufgelistete T-SQL zum Auffinden nullfähiger Spalten ohne Nullen stammt ebenfalls von SQL Server.

Matthew Sontum
quelle
1
Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
Paul White