Tinyint vs Bit?

81

Ich möchte hier keinen Religionskrieg auslösen, aber es scheint zwei Denkschulen zu geben, wie man boolesche Werte in einer Datenbank darstellt. Einige sagen, es bitsei der geeignete Datentyp, während andere argumentieren, es tinyintsei besser.

Die einzigen Unterschiede, die mir bekannt sind, sind folgende:

  • bit: Speichergröße ist 1 Bit, mögliche Werte sind 0 oder 1
  • tinyint: Speichergröße ist 1 Byte, mögliche Werte sind 0-255

Welcher Datentyp ist besser, wenn Sie boolesche Werte darstellen müssen? Lohnt sich tinyintder zusätzliche Aufwand "nur für den Fall", dass Sie Werte> 1 benötigen?

Seibar
quelle
1
"Nur für den Fall" scheint ein ziemlich flüssiges Datenbankdesign zu sein. Warum speichern Sie nicht alles als NVARCHAR (MAX) und decken alle Ihre Basen ab?
Stuart Ainsworth
TinyInt ist meine Präferenz. Wenn Sie dann aggregierte Zählungen für das Feld durchführen, müssen Sie es nicht wirken. Außerdem interpretieren einige Front-End-Sprachen ein Bit anders als andere, und die Verwendung eines TinyInt macht Validierungsprüfungen für jede Front-End-Sprache universell.
Gregory Hart
Ich bin gerade auf eine Kuriosität mit Bit in phpMyAdmin gestoßen. Wenn ich ihm sage, dass das Feld NULL sein soll und kein Standardwert festgelegt ist, wird standardmäßig <em> NULL </ em> anstelle von NULL verwendet. +1 für tinyint übrigens
Vörös Amadea
Beim Importieren der Formular-CSV-Datei 1 funktioniert dies im Fall von tinyint (1), aber im Fall von Bit (1) müssen Sie es durch b'1 'ersetzen
Rajat

Antworten:

90

Wenn Sie Ihrer Tabelle eine Bitspalte hinzufügen, belegt diese in jedem Datensatz ein ganzes Byte und nicht nur ein einzelnes Bit. Wenn Sie eine zweite Bitspalte hinzufügen, wird diese im selben Byte gespeichert. Die neunte Bitspalte benötigt ein zweites Byte Speicher. Tabellen mit 1-Bit-Spalte erhalten keinen Speichervorteil.

Tinyint und Bit können beide zum Arbeiten gebracht werden, ich habe beide erfolgreich verwendet und habe keine starke Präferenz.

ScottS
quelle
Das ist ein sehr hilfreicher Kommentar und Ihr Ruf ist ziemlich gut, aber haben Sie Referenzen, die ihn unterstützen? Handelt es sich um ein Implementierungsdetail oder gehen alle Engines gleich damit um?
Jon z
3
@ Jonz Siehe hier für MySQL.
Shmosel
19

Bit ... es sei denn, Sie gehören dem Clan "true / false / file not found" an

Falls Sie die Referenz nicht erhalten haben ...

Und im Fall von Linq2SQL arbeitet Bit mit true / false, was die Programmierung erleichtert. Beides hat Vorteile.

Außerdem muss die Programmierwartung berücksichtigt werden. Was passiert, wenn Sie (oder ein Junior-Praktikant) 2, 3, 25, 41, 167, 200 usw. verwenden? Wo ist das dokumentiert? Bits sind selbstdokumentierend und ziemlich universell.

Mike Robinson
quelle
11
Bits sind nullwertfähig, sodass Sie weiterhin T / F / FNF haben können.
Austin Salonen
3
Und wie böse ist NULL gleich FNF? :) Wirklich würdig des täglichen Lebens!
John Rudy
@Pratik das Problem ist NULL bedeutet, dass es keinen Wert in der Datenbank gibt. Dies bedeutet nicht, dass die Datei nicht gefunden wurde. Wenn Sie dies tun, beginnen Sie, Zustände implizit in Ihre Zeilen zu codieren, die schwer zu dokumentieren und verwirrend sind. Ein bisschen wie eine Tabelle mit Gegenständen. Wie sehe ich, ob ein Artikel verkauft wurde? Ich könnte nachsehen, ob es einen Verkaufspreis, ein Verkaufsdatum, einen Käufernamen usw. gibt. Oder ich könnte all das mit einer Kontrollbeschränkung durchsetzen und ein Bitfeld für verkaufte Artikel erstellen.
CodeMonkey
15

Ich benutze Bits, wenn es angebracht ist. Abgesehen davon, dass es semantisch der richtige Typ ist (Anzahl der Semantiken!), Können mehrere Bitfelder (bis zu 8) in einer einzelnen Zeile (jedenfalls unter SQL Server) in einem einzigen Speicherbyte konsolidiert werden. Nach dem achten wird ein zusätzliches Byte für die nächsten 8 benötigt und so weiter.

Verweise:

John Rudy
quelle
5

Für MySQL-Benutzer - Warum Sie in MySQL keine BIT-Spalten verwenden sollten

Armandino
quelle
12
Hmmm, sieht eher aus wie ein "Warum Sie MySQL nicht verwenden sollten" -Eintrag ... :-)
Brian Knoblauch
1
behoben: In 5.0.23, 5.1.12 Änderungsprotokollen vermerkt. BIT-Spalten in einer Tabelle können dazu führen, dass Verknüpfungen, die die Tabelle verwenden, fehlschlagen.
Antti Rytsölä
2

Boolean erlaubt per Definition nur zwei Werte. Warum brauchen Sie dafür mehr als ein einziges Bit? Wenn Sie eine Logik mit drei (oder mehr) Zuständen benötigen, verwenden Sie einen größeren Datentyp, aber ich würde (und würde) bei Bitfeldern für die Standard-Boolesche Logik bleiben.

Tvanfosson
quelle
2

Ich verwende Bit, weil ich dadurch keine Prüfbedingung verwenden muss und weil mein ORM das Bit automatisch in einen nullbaren Booleschen Wert (C #) konvertiert, was ich nach dem Codieren sehr schätze.

RedFilter
quelle
2

Null Platz für Falsch

Unabhängig von Ihrer Wahl können Sie NULLstattdessen festlegen, 0dass kein zusätzlicher Speicherplatz belegt wird (da die Datenbank fast immer ein NULLFlag für jedes Feld jeder Zeile enthält, das nur dort sitzt; weitere Informationen hier ). Wenn Sie auch sicherstellen, dass der Standardwert / wahrscheinlichste Wert ist false, sparen Sie noch mehr Platz!

Etwas Platz für Wahr

Der darzustellende Wert trueerfordert den durch den Feldtyp definierten Platz. Mit using BITwird nur dann Platz gespart, wenn eine Tabelle mehrere solcher Spalten enthält, da ein Byte pro 8 Felder verwendet wird (gegenüber TINYINTeinem Byte pro Feld).

TINYINTbietet den Vorteil, dass Sie eine Bitmaske mit 8 Werten anpassen können, ohne sich um die Verwaltung einer Reihe zusätzlicher Spalten kümmern zu müssen, und die Suche ist theoretisch schneller (ein einzelnes ganzzahliges Feld im Vergleich zu mehreren Bitfeldern). Es gibt jedoch einige Nachteile, wie z. B. eine langsamere Reihenfolge, ausgefallene Cross-Indexing-Funktionen und das Fehlen von Feldnamen. Was für mich der größte Verlust ist; Ihre Datenbank würde eine externe Dokumentation erfordern, um festzustellen, welche Bits was in welchen Bitmasken getan haben.

Vermeiden Sie auf jeden Fall die Versuchung, TEXTFelder zum Speichern von Booleschen Werten oder Mengen davon zu verwenden. Das Durchsuchen von Text ist für den Server viel aufwändiger, und beliebige Benennungsschemata wie "Ein, Aus, Aus" können die Interoperabilität beeinträchtigen.

Beejor
quelle
1

Ich habe gerade versucht, auf Bit (SQL Server 2k5) zu gruppieren, und es hat bei mir gut funktioniert. Ich verwende gerne den richtigen Datentyp für die Anwendung. Wenn es ein wahres / falsches Feld ist, dann ist Bit das, was ich benutze ...

rauben
quelle
1

All diese theoretischen Diskussionen sind großartig, aber in der Realität ist es, zumindest wenn Sie MySQL und wirklich auch für SQLServer verwenden, am besten, nicht-binäre Daten für Ihre Booleschen Werte beizubehalten, aus dem einfachen Grund, dass es einfacher ist, mit ihnen zu arbeiten geben die Daten aus, fragen ab und so weiter. Dies ist besonders wichtig, wenn Sie versuchen, eine Interoperabilität zwischen MySQL und SQLServer zu erreichen (dh Sie synchronisieren Daten zwischen beiden), da die Behandlung des BIT-Datentyps in beiden Fällen unterschiedlich ist. In der Praxis werden Sie also viel weniger Probleme haben, wenn Sie sich an einen numerischen Datentyp halten. Ich würde MySQL empfehlen, bei BOOL oder BOOLEAN zu bleiben, die als TINYINT (1) gespeichert werden. Selbst die Art und Weise, wie MySQL Workbench und MySQL Administrator den BIT-Datentyp anzeigen, ist nicht gut (es ist ein kleines Symbol für Binärdaten).

Sheldmandu
quelle
1

Ich glaube nicht, dass ich es oben erwähnt habe, aber es gibt das Problem, dass BIT-Spalten (z. B. MIN, MAX und insbesondere SUM) nicht aggregiert werden können. Ich habe gerade mit 2008 getestet und das Problem ist immer noch da. Das ist der Hauptgrund, warum ich in letzter Zeit tinyint verwende - das andere ist, dass ich mag, wie tinyint skaliert - es ist immer ein Schmerz, wenn Ihr "Zwei-Wert" -Bit-Flag plötzlich mehr mögliche Werte benötigt.

Saldag
quelle
1
Sie können sie aggregieren, indem Sie sie in einen anderen Datentyp umwandeln. Warum sollten Sie jedoch wahr / falsch summieren müssen?
Martin Smith
2
Wir gruppieren häufig ein Feld und fassen zusammen, wie viele eines anderen Feldes für jede Gruppe nach Ergebnis zutreffen. Die Alternative zur Summe besteht darin, das gesamte Ergebnis in Code zurückzugeben und dort zu schleifen, was manchmal dazu führt, dass 1000x mehr Daten an den Client zurückgegeben werden . Aber das Casting beseitigt das, so dass es kein Problem ist.
David Mårtensson
0

Wir erstellen alle unsere Tabellen mit einem int "Vektor" -Feld. Wir verwenden dieses Feld dann als Sammlung von 32 Bits, die wir für jeden Zweck zuweisen können. (Möglicherweise wird eine Gruppe von Bits für eine Reihe von Zuständen verwendet). Vermeidet, dass wir ständig Flaggenfelder hinzufügen müssen, wenn wir dies vergessen.

Joe
quelle
2
Es wird auch Verschleierung genannt. Oder für den Laien "Wartungsalptraum".
Robert C. Barth
6
Sie können einfach alle Ihre Tabellen zu einer einzigen TEXT-Spalte machen und alles durch Kommas getrennt einfügen. Dann müssten Sie Ihr Datenmodell niemals ändern.
Tom H
1
Wir haben eine einzigartige Umgebung. Wir haben extrem große Datenmengen UND die Verfügbarkeit von 4 9, daher ist das Ändern von Tabellen eher untragbar (doppelt so hoch wie bei der Replikation). Wir verfolgen alle Bits an einem zentralen Ort, um Wartungsprobleme zu vermeiden.
Joe
0

@ Kevin: Ich glaube, Sie können group byauf Bitfeldern verwenden (SQL Server 2005):

declare @t table (
    descr varchar(10),
    myBit1 bit, 
    myBit2 bit
)
insert into @t values ('test1', 0, 1)
insert into @t values ('test2', 1, 0)
insert into @t values ('test3', 1, 1)
insert into @t values ('test4', 0, 0)

select myBit1, count(myBit1) from @t group by myBit1
select myBit2, count(myBit1) from @t group by myBit2

Ergebnisse:

myBit1 
------ -----------
0      2
1      2

myBit2 
------ -----------
0      2
1      2
Seibar
quelle
0

TinyInt ist meine Präferenz. Wenn Sie dann aggregierte Zählungen für das Feld durchführen, müssen Sie es nicht wirken. Außerdem interpretieren einige Front-End-Sprachen ein Bit anders als andere, und die Verwendung eines TinyInt macht Validierungsprüfungen für jede Front-End-Sprache universell.

Gregory Hart
quelle
-2

Ich benutze gerne char (1) mit 'T' oder 'F'. Ja, es kann mit anderen Werten missbraucht werden, aber zumindest ist es einfach, es in Berichten oder an anderen Stellen anzuzeigen, an denen es schwieriger ist, mit Bit- oder Binärwerten zu arbeiten.

Darryl Braaten
quelle
2
Sie können (und sollten) der Spalte einfach eine Einschränkung hinzufügen, um nur "T" und "F" zuzulassen. Davon abgesehen sollte die Berichtsschicht VOLLSTÄNDIG von der Datenbank getrennt sein. Sie sollten Ihr Datenbankschema nicht nur zum Zwecke der Anzeige einer Spalte ändern.
Tom H
Ich stimme Darryl zu. Angesichts der mangelnden Unterstützung für boolesche Typen in allgemeinen RDBMS-Systemen (MySQL ist hier nicht allein) ist T / F (eigentlich bevorzuge ich J / N) viel besser lesbar. Obwohl ich den Kommentaren von Tom H grundsätzlich zustimme, denke ich, dass die Lesbarkeit viel wichtiger ist, als er anerkennt. Datenbankentwickler schauen beim Ändern des Codes eines anderen nicht auf das Frontend! Außerdem ist nicht immer klar, in welche Richtung ein Entwickler 1 und 0 betrachtet. Wenn wir es alle auf die "richtige" altmodische Weise tun würden, würden wir verwenden -1, um wahr und 0falsch darzustellen.
Cartbeforehorse
Zu meinem vorherigen Kommentar sollte ich hinzufügen, dass MySQL anscheinend keine CHECK-Einschränkungen unterstützt, was die T / F-Option erschweren würde, da Sie nicht verhindern können, dass die Spalte mit einem anderen Zeichen des Alphabets gefüllt wird. Nicht nett.
Cartbeforehorse