Warum MySQL die Verwendung von Nullspalten mit Standardwerten nicht empfiehlt

Warum MySQL die Verwendung von Nullspalten mit Standardwerten nicht empfiehlt

Die Antwort, die Sie oft hören, ist, dass die Verwendung eines NULL-Werts in einer Spalte den Index ungültig macht, aber wenn Sie es tatsächlich testen, werden Sie wissen, dass IS NULL den Index verwendet. Die obige Anweisung hat also eine Lücke.

Diejenigen, die es kaum erwarten können, können bis zum Ende scrollen, um das Fazit zu sehen

Vorwort

Null ist eine spezielle Einschränkung von Spalten.
Den Spalten in der Tabelle wird eine Nullbeschränkung hinzugefügt, wenn Sie die Spalte nicht explizit mit dem Schlüsselwort "nicht null" definieren.
beim Erstellen der Tabelle.Viele Programmierer definieren Spalten gerne standardmäßig
wegen der Bequemlichkeiten (Verringerung des Urteilscodes der Nichtigkeit), was folglich
kann zu Unsicherheiten bei der Abfrage und einer schlechten Leistung der Datenbank führen.

Der NULL-Wert ist eine spezielle Einschränkung für eine Spalte. Wenn wir beim Erstellen einer neuen Spalte nicht explizit das Schlüsselwort not null verwenden, um die Datenspalte zu deklarieren, fügt Mysql standardmäßig die NULL-Einschränkung für uns hinzu.
Einige Entwickler verwenden die empfohlenen Standardeinstellungen von MySQL direkt beim Erstellen von Datentabellen, da sie dies aus Bequemlichkeit tun (d. h. sie erlauben die Verwendung von NULL-Werten in Feldern). Diese schlechte Angewohnheit kann leicht zu unsicheren Abfrageergebnissen führen und die Datenbankleistung in Szenarien beeinträchtigen, in denen NULL verwendet wird.

Einführen

„Null ist null“ bedeutet, dass es überhaupt nichts ist. Wir können uns nicht vorstellen, dass „Null gleich '' ist, und das sind völlig verschiedene Dinge.
MySQL bietet drei Operatoren zum Verarbeiten von Nullwerten: „IS NULL“, „IS NOT NULL“, „<=>“ und eine Funktion ifnull().
IS NULL: Gibt true zurück, wenn der Spaltenwert null ist.
IS NOT NULL: Gibt „true“ zurück, wenn der Spaltenwert nicht null ist.
<=>: Dies ist ein Vergleichsoperator ähnlich zu "=", aber nicht dasselbe. Er gibt „true“ zurück, sogar für die beiden Nullwerte.
(z. B. ist null <=> null zulässig)
IFNULL(): Geben Sie zwei Eingabeparameter an. Wenn der erste ein Nullwert ist, wird der zweite zurückgegeben.
Ähnlich verhält es sich mit der NVL()-Funktion von Oracle.

NULL bedeutet nicht nichts. Wir sollten beachten, dass NULL und '' (Nullwert) zwei völlig unterschiedliche Werte sind. Es gibt drei Hauptoperatoren, die NULL-Werte in MySQL verarbeiten können.

  • IST NULL
  • IST NICHT NULL
  • <=> Raumschiffoperator, dieser Operator ist = sehr ähnlich, select NULL<=>NULL kann true zurückgeben, aber select NULL=NULL gibt false zurück.
  • IFNULL ist eine Funktion. Sie können selbst herausfinden, wie man sie benutzt... Ich weiß jedenfalls, wie man sie benutzt.

Beispiel

Null gibt beim Vergleich mit anderen Werten außer Null mit „<=>“ niemals „true“ zurück.
Der Vergleich von NULL mit einem beliebigen anderen Wert und einem beliebigen Operator ergibt NULL, außer <=>.

(root@localhost mysql3306.sock)[zlm]>Tabelle erstellen test_null(
    -> id int ungleich null,
    -> Name varchar(10)
    -> );
Abfrage OK, 0 Zeilen betroffen (0,02 Sek.)

(root@localhost mysql3306.sock)[zlm]>in test_null Werte einfügen(1,'zlm');
Abfrage OK, 1 Zeile betroffen (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>in test_null Werte einfügen(2,null);
Abfrage OK, 1 Zeile betroffen (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>Wählen Sie * aus test_null;
+----+------+
| Ich würde | Name |
+----+------+
| 1 | zlm |
| 2 | NULL |
+----+------+
2 Zeilen im Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>Wählen Sie * aus test_null, wobei Name = null ist;
Leerer Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>select * from test_null, wobei Name null ist;
+----+------+
| Ich würde | Name |
+----+------+
| 2 | NULL |
+----+------+
1 Zeile im Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>select * from test_null, wobei Name nicht null ist;
+----+------+
| Ich würde | Name |
+----+------+
| 1 | zlm |
+----+------+
1 Zeile im Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>select * from test_null, wobei null=null;
Leerer Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>Wählen Sie * aus test_null, wobei null<>null;
Leerer Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>Wählen Sie * aus test_null, wobei null <=> null;
+----+------+
| Ich würde | Name |
+----+------+
| 1 | zlm |
| 2 | NULL |
+----+------+
2 Zeilen im Satz (0,00 Sek.)

//null<=>null gibt immer true zurück, es ist gleich „wobei 1=1“.

Null bedeutet „ein fehlender und unbekannter Wert“. Sehen wir uns die Details unten an.
NULL stellt einen unbestimmten Wert dar. Selbst wenn es zwei NULL-Werte gibt, sind sie nicht unbedingt gleich. (Es ist wie eine nicht initialisierte lokale Variable in C.)

(root@localhost mysql3306.sock)[zlm]>SELECT 0 IST NULL, 0 IST NICHT NULL, '' IST NULL, '' IST NICHT NULL;
+-----------+--------------+------------+----------------+
| 0 IST NULL | 0 IST NICHT NULL | '' IST NULL | '' IST NICHT NULL |
+-----------+--------------+------------+----------------+
| 0 | 1 | 0 | 1 |
+-----------+--------------+------------+----------------+
1 Zeile im Satz (0,00 Sek.)

//Es ist nicht gleich einer Nullzahl oder einem leeren String.
//In MySQL bedeutet 0 falsch und 1 wahr.

(root@localhost mysql3306.sock)[zlm]>SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+--------------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+--------------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+--------------+----------+----------+
1 Zeile im Satz (0,00 Sek.)

//Es kann nicht mit einer Zahl verglichen werden.
//In MySQL bedeutet null auch falsch.

Wenn ein beliebiger Ausdruck einen Nullwert enthält, wird als Ergebnis Null ausgegeben.
Jeder Ausdruck, der einen Wert zurückgibt, der NULL enthält, führt zu einem weiteren NULL-Wert.

(root@localhost mysql3306.sock)[zlm]>Auswählen ifnull(null,'Erstes ist null'),ifnull(null+10,'Erstes ist null'),ifnull(concat('abc',null),'Erstes ist null');
+------------------------------+---------------------------------+--------------------------------------------+
| ifnull(null,'Erstes ist null') | ifnull(null+10,'Erstes ist null') | ifnull(concat('abc',null),'Erstes ist null') |
+------------------------------+---------------------------------+--------------------------------------------+
| Erstes ist null | Erstes ist null | Erstes ist null |
+------------------------------+---------------------------------+--------------------------------------------+
1 Zeile im Satz (0,00 Sek.)

//Der Nullwert muss mit der Funktion ifnull() entsorgt werden, was normalerweise zu einer Komplexität der SQL-Anweisung führt.
//Wie wir alle wissen, unterstützt MySQL keine Funktionsindizes. Daher können Indizes für die Spalte möglicherweise nicht verwendet werden. Das ist wirklich schlimmer.

Anders verhält es sich, wenn count(*) und count(null column) verwendet werden.
Die Ergebnisse der Verwendung von count(*) oder count(null column) sind unterschiedlich, count(null column)<=count(*).

(root@localhost mysql3306.sock)[zlm]>Wählen Sie count(*),count(name) aus test_null aus;
+----------+----------+
| Anzahl(*) | Anzahl(Name) |
+----------+----------+
| 2 | 1 |
+----------+----------+
1 Zeile im Satz (0,00 Sek.)

//count(*) gibt alle Zeilen zurück und ignoriert die Nullwerte, während count(name) die von Null verschiedenen Zeilen in der Spalte „name“ zurückgibt.
//Dies führt auch zu Unsicherheiten, wenn jemand die oben genannten Details nicht kennt.

Wenn der Benutzer mit dem NULL-Attribut nicht vertraut ist, kann es leicht zu falschen statistischen Ergebnissen kommen.

Bei der Verwendung von „distinct“, „group by“ und „order by“ werden alle Nullwerte als derselbe Wert betrachtet.
Obwohl das Ergebnis von „select NULL=NULL“ falsch ist, wird NULL als derselbe Wert betrachtet, wenn wir „distinct“, „group by“ und „order by“ verwenden.

(root@localhost mysql3306.sock)[zlm]>in test_null Werte einfügen(3,null);
Abfrage OK, 1 Zeile betroffen (0,00 Sek.)

(root@localhost mysql3306.sock)[zlm]>wählen Sie einen eindeutigen Namen aus test_null aus;
+------+
| Name |
+------+
| zlm |
| NULL |
+------+
2 Zeilen im Satz (0,00 Sek.)

//Zwei Zeilen mit Nullwerten gaben eins zurück und das Ergebnis wurde zwei.

(root@localhost mysql3306.sock)[zlm]>Wählen Sie den Namen aus der Test_null-Gruppe nach Namen aus.
+------+
| Name |
+------+
| NULL |
| zlm |
+------+
2 Zeilen im Satz (0,00 Sek.)

//Zwei Zeilen mit Nullwerten wurden in dieselbe Gruppe eingefügt.
//Standardmäßig sortiert „Group By“ auch das Ergebnis (die Nullzeile wird zuerst angezeigt).

(root@localhost mysql3306.sock)[zlm]>Wählen Sie ID, Name aus test_null aus, sortiert nach Name;
+----+------+
| Ich würde | Name |
+----+------+
| 2 | NULL |
| 3 | NULL |
| 1 | zlm |
+----+------+
3 Zeilen im Satz (0,00 Sek.)

//Drei Zeilen wurden sortiert (zwei Nullzeilen wurden zuerst angezeigt).

MySQL unterstützt die Verwendung eines Index für Spalten, die Nullwerte enthalten (anders als bei Oracle).
MySQL unterstützt die Verwendung von Indizes für Spalten mit NULL-Werten, Oracle hingegen nicht. Normalerweise sagt man, wenn eine Spalte NULL enthält, ist der Index ungültig.
Streng genommen trifft diese Aussage auf MySQL nicht zu.

(root@localhost mysql3306.sock)[sysbench]>Tabellen anzeigen;
+--------------------+
| Tabellen_in_Sysbench |
+--------------------+
|sbtest1|
|sbtest10|
|sbtest2|
|sbtest3|
|sbtest4|
|sbtest5|
|sbtest6|
|sbtest7|
|sbtest8|
|sbtest9|
+--------------------+
10 Zeilen im Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[sysbench]>zeige Tabelle erstellen sbtest1\G
*************************** 1. Reihe ***************************
       Tabelle: sbtest1
Tabelle erstellen: CREATE TABLE `sbtest1` (
  `id` int(11) NICHT NULL AUTO_INCREMENT,
  `k` int(11) NICHT NULL STANDARD '0',
  `c` char(120) NICHT NULL STANDARD '',
  `pad` char(60) NICHT NULL STANDARD '',
  Primärschlüssel (`id`),
  SCHLÜSSEL `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8
1 Zeile im Satz (0,00 Sek.)

(root@localhost mysql3306.sock)[sysbench]>alter table sbtest1 modify k int null, modify c char(120) null, modify pad char(60) null;
Abfrage OK, 0 Zeilen betroffen (4,14 Sek.)
Datensätze: 0 Duplikate: 0 Warnungen: 0

(root@localhost mysql3306.sock)[sysbench]>in sbtest1-Werte einfügen(100001,null,null,null);
Abfrage OK, 1 Zeile betroffen (0,00 Sek.)

(root@localhost mysql3306.sock)[sysbench]>erklären Sie „select id,k from sbtest1 where id=100001;“
+----+----------+---------+------------+-------+---------------+---------+---------+---------+---------+-------+------+------+------+------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+---------+------------+-------+---------------+---------+---------+---------+---------+-------+------+------+------+------+
| 1 | EINFACH | sbtest1 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100,00 | NULL |
+----+----------+---------+------------+-------+---------------+---------+---------+---------+---------+-------+------+------+------+------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

(root@localhost mysql3306.sock)[sysbench]>erklären Sie select id,k from sbtest1, wobei k null ist;
+----+----------+---------+------------+------+---------------+-----+---------+---------+-------+---------+----------+----------+----------+-------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+---------+------------+------+---------------+-----+---------+---------+-------+---------+----------+----------+----------+-------------+
| 1 | SIMPLE | sbtest1 | NULL | ref | k_1 | k_1 | 5 | const | 1 | 100.00 | Mit where; Mit index |
+----+----------+---------+------------+------+---------------+-----+---------+---------+-------+---------+----------+----------+----------+-------------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

//In der ersten Abfrage wird die neu hinzugefügte Zeile per Primärschlüssel abgerufen.
//In der zweiten Abfrage wird die neu hinzugefügte Zeile mit dem Sekundärschlüssel „k_1“ abgerufen.
//Es wurde bewiesen, dass Indizes auf Spalten angewendet werden können, die Nullwerte enthalten.
//Spalte „k“ ist ein int-Datentyp, der 4 Bytes belegt, aber der Wert von „key_len“ ergibt 5. Was ist daran falsch? Weil der Nullwert 1 Byte benötigt, um das Null-Flag in den Zeilen zu speichern.

Dies ist ein Beispiel, das ich selbst getestet habe.

mysql> wähle * aus test_1;
+--------------+------+------+
| Name | Code | ID |
+--------------+------+------+
| gaoyi | wo | 1 |
| w | 2 |
| chuzhong | wo | 3 |
| chuzhong | w | 4 |
| xiaoxue | dd | 5 |
| xiaoxue | dfdf | 6 |
| 99 |
| sujianhui | NULL | 99 |
+--------------+------+------+
8 Zeilen im Satz (0,00 Sek.)

mysql> erläutern Sie „select * from test_1“, wobei der Code NULL ist;
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
| 1 | SIMPLE | test_1 | NULL | ref | index_code | index_code | 161 | const | 1 | 100.00 | Indexbedingung verwenden |
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

mysql> erläutern Sie „select * from test_1“, wobei der Code nicht NULL ist;
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
| 1 | SIMPLE | test_1 | NULL | Bereich | Indexcode | Indexcode | 161 | NULL | 7 | 100,00 | Indexbedingung wird verwendet |
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

mysql> erläutern Sie „select * from test_1 where code='dd';“
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
| 1 | SIMPLE | test_1 | NULL | ref | index_code | index_code | 161 | const | 1 | 100.00 | Indexbedingung verwenden |
+----+----------+--------+------------+------+---------------+-------------+---------+---------+---------+-------+----------+----------+----------+---------------------------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

mysql> erklären Sie select * from test_1, wobei Code wie „dd%“ aussieht;
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
| 1 | SIMPLE | test_1 | NULL | Bereich | Indexcode | Indexcode | 161 | NULL | 1 | 100,00 | Indexbedingung wird verwendet |
+----+----------+--------+------------+-------+---------------+---------------+------------+---------+------+----------+----------+----------+----------------------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Zusammenfassung

Ein Nullwert führt bei der Entsorgung von SQL-Anweisungen immer zu vielen Unsicherheiten. Dies kann unbeabsichtigt zu Leistungseinbußen führen.

Die Verwendung von NULL-Werten in Spalten kann leicht zu unkontrolliertem Verhalten führen und die Systemleistung mitunter erheblich verlangsamen.

Zum Beispiel:

Der Nullwert wird in der Aggregatfunktion () nicht geschätzt, was zu ungenauen Ergebnissen führen kann.
Beim Durchführen statistischer Berechnungen für Spalten mit NULL-Werten, wie etwa count(), max() und min(), entsprechen die Ergebnisse nicht unseren Erwartungen.

Nullwerte beeinflussen das Verhalten von Operationen wie „distinct“, „group by“ und „order by“, was zu einer falschen Sortierung führt.
Beeinträchtigt die Ergebnisse beim Sortieren, Gruppieren und Deduplizieren.

Für die Beurteilung von Nullwerten ist die Funktion ifnull() erforderlich, wodurch der Programmcode komplexer wird.
Um die durch NULL verursachte technische Schuld zu beseitigen, müssen wir manchmal IFNULL() in SQL verwenden, um sicherzustellen, dass die Ergebnisse kontrollierbar sind, aber das kompliziertert das Programm.
Ein Nullwert benötigt ein zusätzliches Byte, um die Nullinformationen in den Zeilen zu speichern.

Der NULL-Wert belegt nicht den ursprünglichen Speicherplatz des Felds, sondern es wird ein zusätzliches Byte zur Markierung verwendet. Dieses Feld fügt eine NULL-Beschränkung hinzu. (Genau wie ein zusätzliches Flag-Bit)
Aufgrund der oben genannten Nachteile wird davon abgeraten, Spalten mit dem Standardwert Null zu definieren.
Wir empfehlen, für alle Spalten „nicht null“ zu definieren und den entsprechenden Null-Datentyp durch eine Nullzahl und eine leere Zeichenfolge zu ersetzen.

Aufgrund der oben genannten Nachteile empfehlen wir nicht, NULL als Standardwert in einer Spalte festzulegen. Sie können NOT NULL verwenden, um die Standardeinstellung zu eliminieren und anstelle von NULL 0 oder eine leere Zeichenfolge zu verwenden.

Verweise

https://www.cnblogs.com/aaron8219/p/9259379.html

Damit ist dieser Artikel darüber, warum MySQL die Verwendung von Spalten mit Standardwerten von null nicht empfiehlt, abgeschlossen. Weitere Informationen zu MySQL-Standardwerten von null finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Eine bequeme Möglichkeit, mehrere Datenquellen und Mysql-Datenbanken im Springboot-Backend zu konfigurieren
  • Detaillierte Erklärung der MySQL DEFINER-Verwendung
  • Ausführliche Erläuterung der MySQL-Isolationsebene und des Sperrmechanismus
  • Aufbau einer Django-Produktionsumgebung (uWSGI+Django+Nginx+Python+MySQL)
  • Eine kurze Analyse, ob der MySQL-Primärschlüssel Zahlen oder UUIDs für schnellere Abfragen verwendet
  • Fallstudie zu MySQL-Berechtigungen und Datenbankdesign
  • So stellen Sie mit Node-Red eine Verbindung zur MySQL-Datenbank her
  • Detaillierte Erklärung von Group By und Having in MySQL

<<:  Detaillierte Erklärung der Nginx-Konfigurationsdatei und Anleitung mit Optimierungsvorschlägen

>>:  Einführung mehrerer benutzerdefinierter Schriftarten in CSS3

Artikel empfehlen

Vergleich der Effizienz verschiedener Methoden zum Löschen von Dateien in Linux

Testen Sie die Effizienz des Löschens einer große...

So führen Sie das Springboot-Projekt im Docker aus

1. Klicken Sie unten in IDEA auf Terminal und geb...

Wie MySQL Milliarden von Datenverkehr unterstützt

Inhaltsverzeichnis 1 Master-Slave-Lese-/Schreibtr...

So legen Sie das Breitenattribut auf den Stil des Span-Tags fest

Wenn Sie das Breitenattribut direkt auf den Stil d...

So verwenden Sie Shell-Skripte in Node

Hintergrund Während der Entwicklung benötigen wir...

Perfekte Lösung zur vertikalen Zentrierung von Formelementen

Code kopieren Der Code lautet wie folgt: <!DOC...