Peter Thomassen: NULL-Byte vs. leeren String

Hallo Forum,

mir ist durchaus bewusst, dass ich zur Zeit bezüglich Datenbanken komische Fragen stelle :-)

Nehmen wir mal eine Tabelle an, die Bemerkungen über die Kreditwürdigkeit von Kunden enthält ;-), die in einer Spalte remark abgelegt werden.

Wenn über einen Kunden keine entsprechenden Informationen vorliegen, soll sein remark-Feld NULL oder '' als Wert bekommen? :-)

Was benötigt eigentlich weniger Speicher / ist schneller? Ein NULL-Byte benötigt doch IMHO dieselben Ressourcen wie ein Zeichen, oder nicht?

Klärt mich auf :-)

Danke!
Peter

  1. Moin!

    Nehmen wir mal eine Tabelle an, die Bemerkungen über die Kreditwürdigkeit von Kunden enthält ;-), die in einer Spalte remark abgelegt werden.

    Wenn über einen Kunden keine entsprechenden Informationen vorliegen, soll sein remark-Feld NULL oder '' als Wert bekommen? :-)

    Brauchst du die Informationen "Bemerkung: Blahblah", "Bemerkung: (leer)" und "Bemerkung: (gibts nicht)"?

    Oder reicht "Bemerkung: Blahblah" und "Bemerkung: (leer)" aus?

    MySQL empfiehlt, so wenig wie möglich NULL-Spalten zu benutzen. Eine NULL-Spalte wäre beispielsweise sinnvoll, wenn du Meßwerte hast und jetzt irgendwie kennzeichnen mußt, dass du auch mal "keinen Meßwert" erfaßt hast. Meßwerte sind Zahlen, und alle Zahlen können als Meßwert vorkommen, also gibts keinen Wert, den man als "nicht erfaßt" nehmen könnte. NULL ist dafür gut.

    Bei Textfeldern braucht man in meinen Augen zu 99% kein NULL.

    Was benötigt eigentlich weniger Speicher / ist schneller? Ein NULL-Byte benötigt doch IMHO dieselben Ressourcen wie ein Zeichen, oder nicht?

    Nein, NULL benötigt ein Bit zusätzlich. Aber immer, bei jedem Datensatz. Deshalb wird die DB dadurch größer, als sie sein müßte.

    - Sven Rautenberg

    --
    "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
    (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
    1. Hallo Sven,

      Brauchst du die Informationen "Bemerkung: Blahblah", "Bemerkung: (leer)" und "Bemerkung: (gibts nicht)"?

      Oder reicht "Bemerkung: Blahblah" und "Bemerkung: (leer)" aus?

      In meinem Falle offensichtlich Letzteres.

      Nein, NULL benötigt ein Bit zusätzlich. Aber immer, bei jedem Datensatz. Deshalb wird die DB dadurch größer, als sie sein müßte.

      Danke!

      Bye,
      Peter

    2. Hallo Sven,

      Brauchst du die Informationen "Bemerkung: Blahblah", "Bemerkung: (leer)" und "Bemerkung: (gibts nicht)"?

      Oder reicht "Bemerkung: Blahblah" und "Bemerkung: (leer)" aus?

      Ist es legitim, den Nullwert zu missbrauchen, um zu beschreiben, dass das Feld (in der Eingabemaske) nicht obligatorisch ist (sprich keinen Wert haben muss, NULL sein darf)?

      Bye,
      Peter

      1. hi,

        Ist es legitim, den Nullwert zu missbrauchen, um zu beschreiben, dass das Feld (in der Eingabemaske) nicht obligatorisch ist (sprich keinen Wert haben muss, NULL sein darf)?

        was ist deine eingabemaske?

        wenn du mit MS Access oder so arbeitest, könnte das evtl. nötig sein (kenne mich damit nicht aus).

        wenn du aber die daten über ein html-formular vom user eingeben lässt, besteht kein direkter zusammenhang zwischen deiner eingabemaske (=formular) und den feldern in der DB. diese verbindung stellst du in deiner formularverarbeitung erst her, also sorge dort dafür, dass bei übergabe _keines_ wertes für ein feld '' in die DB eingetragen wird.

        gruss,
        wahsaga

        1. Hallo wahsaga,

          Ist es legitim, den Nullwert zu missbrauchen, um zu beschreiben, dass das Feld (in der Eingabemaske) nicht obligatorisch ist (sprich keinen Wert haben muss, NULL sein darf)?

          was ist deine eingabemaske?

          [...]

          wenn du aber die daten über ein html-formular vom user eingeben lässt, besteht kein direkter zusammenhang zwischen deiner eingabemaske (=formular) und den feldern in der DB. diese verbindung stellst du in deiner formularverarbeitung erst her, also sorge dort dafür, dass bei übergabe _keines_ wertes für ein feld '' in die DB eingetragen wird.

          Sven sagte etwas anderes.

          Es geht um ein dynamisch erzeugtes HTML-Formular - mit den altbekannten Sternchen zur Kennzeichnung von obligatorischen Feldern. Diese Eigenschaft könnte ich doch daraus ermitteln, ob für eine Spalt NULL (keine Eingabe) erlaubt ist oder nicht - oder liege ich falsch?

          Bye,
          Peter

          1. Moin!

            Sven sagte etwas anderes.

            Aber wahsaga hat trotzdem Recht. :)

            Es geht um ein dynamisch erzeugtes HTML-Formular - mit den altbekannten Sternchen zur Kennzeichnung von obligatorischen Feldern. Diese Eigenschaft könnte ich doch daraus ermitteln, ob für eine Spalt NULL (keine Eingabe) erlaubt ist oder nicht - oder liege ich falsch?

            Ja, theoretisch könntest du vor jeder Formulargenerierung "DESCRIBE TABLE tabelle" machen, die Ausgabe parsen und nachschauen, welche Felder NULL und welche NOT NULL sind.

            Die Information obligatorischer oder nicht-obligatorischer Daten aber derart zu verstecken ist nicht zielführend!

            In MySQL kannst du ja leider keine Constraints definieren, die dich davon abhalten würden, beispielsweise halbausgefüllte Datensätze zu speichern. Diese Kontrolle muß also die Anwendungslogik erfüllen.

            Denn Constraints hin oder her: Die Anwendungslogik muß ja sowieso den SQL-Query abschicken und eine Fehlermeldung dem Benutzer irgendwie verständlich darbieten. Also kann sie das auch gleich direkt machen.

            Wenn du in irgendeiner Weise die "Sternchen an den Feldern" in der Datenbank speichern willst, dann mach dafür eine eigene Tabelle auf, in die du "Feldname", "Feldtyp", "obligatorisch" etc. reinspeicherst. Sofern du überhaupt ein derart dynamisches Formular benötigst.

            Aber du mußt die 1-Bit-Information "Feld ist obligatorisch (oder nicht)" nicht in jeden einzelnen Datensatz reinspeichern. Das ist absolut redundant! Wenn du eine Million Datensätze hast, dann hast du für jedes obligatorische (oder nicht obligatorische - je nachdem, wie deine Logik ist) Formularfeld eine Million Bit verschwendet. Wenn die Datenbank nicht mit Bits operiert, sondern dafür ein ganzes Byte verschwendet: Ein Megabyte an nutzlosen Daten, wo ein einziges Bit gereicht hätte.

            - Sven Rautenberg

            --
            "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
            (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
            1. Hello,

              da habe ich 'was besseres für Dich...

              function get_info($con,$table)
              {
                if (!$con) return false;
                if (strlen($table) == 0) return false;

              $sql = "show columns from $table";
                $res = mysql_query($sql,$con);

              if (!$res) return false;

              $info = array();
                while ($rec = mysql_fetch_assoc($res))
                {
                  $field=$rec["Field"];
                  unset($rec["Field"]);
                  $info["$field"]=$rec;
                }
                return $info;
              }

              returns:

              info[fieldname1]["Type"]

              #                 ["Null"]
              #                 ["Key"]
              #                 ["Default"]
              #                 ["Extra"]

              info[fieldname2][...]

              ...

              Typen sind zur Zeit:

              #   tinyint
              #   smallint
              #   mediumint
              #   int
              #   bigint
              #   float
              #   double
              #   decimal
              #   date
              #   datetime
              #   timestamp
              #   time
              #   year
              #   char
              #   varchar
              #   tinyblob
              #   tinytext
              #   text
              #   blob
              #   mediumblob
              #   mediumtext
              #   longblob
              #   longtext
              #   enum
              #   set

              #-------------------------------------------------------------------------

              Du erhältst ein Array und kannst nun direkt über den Feldnamen auf die Eigenschaften des Feldes zugreifen. Die Art der Darstellung im Browser erfolgt nach dem Datentyp. Ich habe meine Anzeigefunktionen hoffentlich bald fertig.

              Es ist überhaupt keine Vergewaltigung, den NULL-Wert für die Anzeige zu nutzen. Dafür ist er im Prinzip auch da. Er steuert ja das Insert- und Updateverhalten der Tabelle.

              Wenn ich ein Formular an den Browser schicke, trage ich dieses Array unter einer Formular-ID, ergänzt um die Angabe, ob das Feld für den User freigegeben ist, und die Daten in die Session ein. Wenn der POST nun eintrifft, wird unter der Formular-ID geschaut, ob überhaupt einer erwartet wird und ob er nur erlaubte Werte enthält. Wenn nein, gibts was auf die Finger...

              Ich bin nun gerade dabei, an gestaffelten Formularen (Relationen) zu arbeiten. Da kneifen sich aber noch ein paar Ideen. Wäre schön, wenn wir und da mal austauschen könnten.

              Grüße

              Tom

              1. Moin!

                Es ist überhaupt keine Vergewaltigung, den NULL-Wert für die Anzeige zu nutzen. Dafür ist er im Prinzip auch da. Er steuert ja das Insert- und Updateverhalten der Tabelle.

                Doch, ist es.

                Die Information "Formularfeld ist Pflichtfeld" gehört nicht in die Tabellenstruktur hinein!

                Was ist, wenn sich das Formularfeld mal ändert zum Nicht-Pflichtfeld? Dann änderst du die Tabellenstruktur. Und wenn du die von NULL auf NOT NULL änderst, hast du ein Problem mit allen bis dahin eingetragenen NULL-Werten.

                Abgesehen davon ist es Datenverschwendung, wenn nur dafür, dass das Formularfeld mal Pflichtfeld war, in jedem _Datensatz_ ein Bit für NULL freigehalten wird, was aber nicht wirklich benutzt wird.

                Wenn ich ein Formular an den Browser schicke, trage ich dieses Array unter einer Formular-ID, ergänzt um die Angabe, ob das Feld für den User freigegeben ist, und die Daten in die Session ein. Wenn der POST nun eintrifft, wird unter der Formular-ID geschaut, ob überhaupt einer erwartet wird und ob er nur erlaubte Werte enthält. Wenn nein, gibts was auf die Finger...

                Dann hast du aber auch megawichtige Formulardinge am Laufen. Üblicherweise reicht ein eher entspanntes Umgehen mit Formularen eigentlich aus. Ein Formmailer braucht keine Datenbankanbindung für Pflichtfelder.

                Abgesehen davon: Du machst doch so gern mit Sessions. _Da_ würden diese Daten gut reinpassen, nicht in die Datenbank.

                - Sven Rautenberg

                --
                "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
                (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
                1. Hello,

                  Was ist, wenn sich das Formularfeld mal ändert zum Nicht-Pflichtfeld? Dann änderst du die Tabellenstruktur. Und wenn du die von NULL auf NOT NULL änderst, hast du ein Problem mit allen bis dahin eingetragenen NULL-Werten.

                  Dann muss doch sowieso migriert werden! Die Sätze, die NULL enthalten, müssen dann doch nachgepflegt werden.

                  Abgesehen davon ist es Datenverschwendung, wenn nur dafür, dass das Formularfeld mal Pflichtfeld war, in jedem _Datensatz_ ein Bit für NULL freigehalten wird, was aber nicht wirklich benutzt wird.

                  Darauf gehe ich noch ein, wenn ich das genauer untersucht habe. Ich habe nämlich den Eindruck, dass NULL-Kennzeichnung durchaus Platz sparen kann.

                  Dann hast du aber auch megawichtige Formulardinge am Laufen. Üblicherweise reicht ein eher entspanntes Umgehen mit Formularen eigentlich aus. Ein Formmailer braucht keine Datenbankanbindung für Pflichtfelder.

                  Wenn die Daten aus der DB kommen oder dorthin gehen, ja. Auch wenn sie irgendwo versickern, müssen sie trotzdem geprüft werden.

                  Aber vielen Dank für den Hinweis. Hilft mir vielleicht bei der Relationsbindung der Formulare...

                  Abgesehen davon: Du machst doch so gern mit Sessions. _Da_ würden diese Daten gut reinpassen, nicht in die Datenbank.

                  Habe ich auch geschrieben, dass sie da stehen. Aber irgendwo müssen sie ja ursprünglich herkommen. Die Session denkt sich zum Glück nix selbst aus *grins*

                  Tom

                2. Hi Sven

                  Die Information "Formularfeld ist Pflichtfeld" gehört nicht in die Tabellenstruktur hinein!

                  Die Information die in Null gespeichert wird, ist, dieses Feld muss nicht zwingend gesetzt werden. Das ist eine Information auf Datenebene. Eine Entscheidung ob ein Formularfeld Pflicht ist, entsteht aus dem Datenmodell.Darum gehört so eine Information für mich durchaus in die Datenbank.

                  Ich würds mir aus anderen Gründen aber trotzdem nicht antun. In Perl (evtl auch PHP) sind Null-Werte einfach zu handhaben da diese auch den Wert undef kennen. Aber beispielsweise in PL/1 oder C wo so einfach nicht zu erkennen ist, ob eine Variable definiert ist oder nicht, wird das ganze ziemlich mühsam (geht eigentlich nur über zusätzliche Variablen).

                  Gruss Daniela

                  1. Hello Daniela,

                    Die Information die in Null gespeichert wird, ist, dieses Feld muss nicht zwingend gesetzt werden. Das ist eine Information auf Datenebene. Eine Entscheidung ob ein Formularfeld Pflicht ist, entsteht aus dem Datenmodell.Darum gehört so eine Information für mich durchaus in die Datenbank.

                    Mich würde interessieren, ob MySQL überhaupt Rücksicht auf dieses Feld nimmt. Bei Textfeldern kann in NULL soviel YES drinstehen wie es will, da kann ich keinen Unterschied im Verhalten feststellen. Oder liegt das an meiner Version 3.23.55-max?

                    Bei numerischen Feldern wird dann die Ziffer 0 eingeblendet.

                    In der Datenstruktur (TEST.MYD) konnte ich auch keine Unterschiede feststellen. Hast Du so ganz zuuufällig irgendwo einen Link auf ne Page, wo die Datenstruktur von MyISAM erläutert wird?

                    Grüße

                    Tom

                  2. Moin!

                    Die Information "Formularfeld ist Pflichtfeld" gehört nicht in die Tabellenstruktur hinein!

                    Die Information die in Null gespeichert wird, ist, dieses Feld muss nicht zwingend gesetzt werden. Das ist eine Information auf Datenebene. Eine Entscheidung ob ein Formularfeld Pflicht ist, entsteht aus dem Datenmodell.Darum gehört so eine Information für mich durchaus in die Datenbank.

                    Ja, in die Datenbank gehört diese Information schon irgendwie hinein. Eine "echte" Datenbank könnte man wahrscheinlich mit Constraints darauf trainieren, dass nur Requests angenommen werden, die den festgelegten Regeln entsprechen (und das wären z.B. eben Pflichtfelder, die ausgefüllt sein müssen, andernfalls wird der Request zurückgewiesen).

                    Aber eine NULL-Spalte führt eben in jedem Datensatz ein Bit mit, das nichts wirklich zu tun hat.

                    Allenfalls bei Zahlendatentypen kann man den Unterschied "NULL/nicht NULL" feststellen: Wenn das <input> leergelassen wird, dann soll NULL eingetragen werden, wenn eine Zahl drinsteht, wird die eingetragen, und wenn keine Zahl drinsteht, muß man den Benutzer nochmal fragen, was das sollte.

                    Bei der Abfrage eines Strings hingegen kann man das nur anhand des Datenfeldes nicht mehr feststellen. Leerstring _kann_ NULL bedeuten, es kann aber auch "Leerstring" bedeuten. Wenn man Leerstring immer mit NULL übersetzt, braucht man NULL nicht, weil man auch den Leerstring nehmen könnte. Um die Unterscheidung treffen zu können, muß eine Zusatzinformation (z.B. eine Checkbox) hinzugefügt werden, mit der man regelt, ob das Feld jetzt leer ist, oder NULL.

                    NULL hat in meinen Augen schlicht eine andere Bedeutung, als hier verlangt wird. Es kennzeichnet eben den (nur bei gewissen Daten wirklich notwendigen) Zustand "undefiniert". In einem Webformular sind aber grundsätzlich alle Daten definiert. Und die Sicherstellung, dass Pflichtfelder auch tatsächlich ausgefüllt sind, unterstützt MySQL ja auch in keiner Weise, das ist alles der Anwendungslogik vorbehalten.

                    - Sven Rautenberg

                    --
                    "Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
                    (fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)
          2. hi,

            Es geht um ein dynamisch erzeugtes HTML-Formular - mit den altbekannten Sternchen zur Kennzeichnung von obligatorischen Feldern. Diese Eigenschaft könnte ich doch daraus ermitteln, ob für eine Spalt NULL (keine Eingabe) erlaubt ist oder nicht - oder liege ich falsch?

            ja sicher, das könntest du natürlich.

            wenn das formular wirklich so dynamisch sein _muss_ (ändert sich die tabellenstruktur denn derart oft, dass dies sinnvoll wäre? jedes mal für die ausgabe des formulares erst die tabellenstruktur zu analysieren kommt mir recht unperformant vor ...)

            _wenn_ du das also so willst, dann musst du den kleinen "nachteil", dass NULL eben immer ein byte mehr platz verbraucht, wohl in kauf nehmen.

            gruss,
            wahsaga