Wann sollte TINYINT über INT verwendet werden?

91

Im Allgemeinen verwende ich immer Ints. Ich weiß, dass dies theoretisch nicht die beste Vorgehensweise ist, da Sie den kleinsten Datentyp verwenden sollten , der die Daten garantiert speichert.

Zum Beispiel ist es besser zu verwenden, tinyintwenn Sie wissen, dass die einzigen Daten, die Sie speichern, eine 1, 0 oder Null sind (mit einer sehr geringen Chance, diese später auf 2 oder 3 zu erweitern).

Der einzige Grund, den ich dafür kenne, ist zu Speicherzwecken - Verwendung von 1 Byte in einer Zeile anstelle von 4 Byte.

Was sind die Auswirkungen der Verwendung tinyint(oder smallintsogar bigint) von mehr als nur intPlatz auf Ihrer Festplatte zu sparen?

Richard
quelle
2
Dies ist eine sehr schöne Frage (+1). MySQL hat SELECT ... PROCEDURE ANALYZE (), das tatsächlich die kleinsten Datentypen empfiehlt, die die Tabelle für das angegebene SELECT haben sollte. Das war zum Teil die Inspiration für meine Antwort.
RolandoMySQLDBA
3
Gute Frage, aber um genau zu sein ist der winzige Bereich 0-255. Das Bitfeld ist 0 oder 1 (oder NULL). Die Speicherkosten für einen Tinyint betragen 1 Byte. Alle 8-Bit-Felder in einer Tabelle kosten 1 Byte Speicher. msdn.microsoft.com/en-us/library/ms187745.aspx und msdn.microsoft.com/en-us/library/ms177603.aspx
billinkc
@billinkc Richtig. Aus diesem Grund habe ich die Möglichkeit erwähnt, die Spalte um die Werte 2 oder 3 zu erweitern. Wenn Sie 2 oder 3 einschließen, müssen Sie tinyint (im kleinsten Maßstab) verwenden.
Richard
1
"Beispielsweise ist es besser, tinyint zu verwenden, wenn Sie wissen, dass die einzigen Daten, die Sie speichern, eine 1, 0 oder Null sind (mit einer sehr geringen Chance, diese Zahl später auf 2 oder 3 zu erweitern)." Ich würde ein ENUM für so etwas verwenden. Diese werden als Bitfelder gespeichert, und wie viele andere hier ausgeführt haben, führen kleine Einsparungen pro Datensatz zu großen Einsparungen in der gesamten Datenbank - auch mehr, wenn die Spalte indiziert ist.
2
@ user6665 I'd use an ENUM for such a thing.Nicht in SQL Server, Sie würden nicht, da es keine Aufzählungen jeglicher Art hat.
Underscore_d

Antworten:

92

Speicherplatz ist billig ... das ist nicht der Punkt!

Denken Sie nicht mehr an Speicherplatz, sondern an Pufferpool und Speicherbandbreite . Am äußersten Ende CPU-Cache und Speicherbusbandbreite . Der verknüpfte Artikel ist Teil der Reihe, in der Probleme mit der Auswahl von schlecht gruppierten Schlüsseln (INT vs GUID vs Sequential GUID) hervorgehoben werden, aber der Unterschied, den Bytes machen können, wird hervorgehoben.

Die übergeordnete Botschaft ist das Design. Der Unterschied wird nicht in einer einzelnen Datenbank auf einem entsprechend spezifizierten Server angezeigt, bis Sie das Gebiet der VLDB erreichen. Wenn Sie jedoch ein paar Bytes sparen können, warum nicht.

Ich werde an die Umgebung erinnert, die in einer früheren Frage beschrieben wurde . Über 400 Datenbanken mit einer Größe von 50 MB bis 50 GB pro SQL-Instanz. Das Scrubben einiger Bytes pro Datensatz, pro Tabelle und pro Datenbank in dieser Umgebung kann einen signifikanten Unterschied bewirken.

Mark Storey-Smith
quelle
29

Neben den anderen Antworten ...

Zeilen und Indexeinträge werden auf 8.000 Seiten gespeichert. Eine Million Zeilen mit 3 Bytes pro Zeile entspricht also nicht 3 MB auf der Festplatte. Dies wirkt sich auf die Anzahl der Zeilen pro Seite aus ("Seitendichte").

Gleiches gilt für nvarchar bis varchar, smalldatetime bis datetime, int bis tinyint etc

Edit, Juni 2013

http://sqlblog.com/blogs/joe_chang/archive/2013/06/16/load-test-manifesto.aspx

Dieser Artikel besagt

Die wichtigen Kriterien sind die Kardinalität und das Seitenverhältnis.

Die Wahl des Datentyps spielt also eine Rolle

gbn
quelle
5
Guter Punkt. Ein absolutes Worst-Case-Beispiel ist eine 4028-Byte-Zeile, die aus Spalten mit fester Länge besteht, denen Sie eine Spalte hinzufügen möchten. Das Hinzufügen einer kleinen Ganzzahl würde Sie zu 4030 (2 Zeilen pro Seite) führen, aber eine Ganzzahl drückt Sie über die Grenze (1 Zeile pro Seite, 4028 verschwendete Bytes pro Seite).
Mark Storey-Smith
Ich habe einmal einen Leistungstest für int vs bigint durchgeführt. Speichern Sie 1 Million Datensätze, vergleichen Sie Zeit und Speicherplatz und rufen Sie sie nacheinander ab, um die Leistung erneut zu messen. Ich habe keine großen Unterschiede gesehen. Ich werde den gleichen Leistungstest für int vs tinyint machen. Ich denke wirklich, dass es für 80% der Anwendungen vernachlässigt werden kann, was zu konsistenteren Datentypen und geringeren Wartungskosten führt.
Saeed Neamati
1
@ SaeedNeamati Vielleicht möchten Sie den Artikel aus Marks Antwort noch einmal lesen (" Haben Sie jemals gehört ... lasst uns das einfach erledigen - wir sorgen uns später um die Leistung? ... ich höre das die ganze Zeit ... ") und gbn ist da . Ich denke, dass das mit nach Hause nehmen ist, dass jede ineffiziente Wahl seine Streifen in der richtigen Skala zeigen wird, und OPs Darm ist nicht falsch.
Ruffin
14

Es kommt nicht nur auf den Tischspeicher an. Wenn Sie Indizes verwenden, bei denen die Spalte int Teil eines zusammengesetzten Schlüssels ist, möchten Sie natürlich, dass die Indexseiten so voll wie möglich sind, da die Indexeinträge so klein wie möglich sind.

Ich würde definitiv erwarten, dass das Untersuchen von Indexeinträgen in BTREE-Seiten mit kleineren Datentypen etwas schneller ist. Alle VARCHARs, die an Indexeinträgen beteiligt sind, würden jedoch Leistungsgewinne aus der Verwendung von TINYINT über INT ausgleichen (aufheben).

Ungeachtet dessen, wenn Indexeinträge zusammengesetzte Einträge haben und alle Ganzzahlen sind, sind die Ganzzahlen umso besser und schneller, je kleiner sie byteweise sind.

RolandoMySQLDBA
quelle
13

Alle Dinge werden komplexer, wenn die Datenbanken größer werden:

  • Wartungsfenster müssen vergrößert oder neu geplant werden
  • Backups (das vollständige Backup am Tagesende wird zu einem absurden Zeitfresser, sodass Sie differenzielle oder sogar Protokoll-Backups benötigen und das Backup einmal pro Woche, möglicherweise einmal im Monat, durchführen müssen)
  • Performances Maintanances werden zu einem Zeitfresser (das Erstellen eines Indexes für eine Tabelle mit mehreren Millionen Zeilen benötigt keine triviale Zeit) und müssen neu geplant werden. Wenn die Tabelle breit ist, verschlechtern sie sich ...
  • Und die Übertragung dieses 100-GB-Backups über das Netzwerk ist nicht das, was ich als Kinderspiel bezeichne - insbesondere, wenn das Netzwerk (aus einem unbekannten Grund) hartnäckig ist, wenn die Verbindung auf die 75-GB-Marke fällt ... sicherte auf einem zugeordneten Laufwerk im Netzwerk (Netzwerk) ...

Und welche Datentypen haben das zu tun? ALLES. Wenn Sie Zeilengrößen verwenden, die größer als erforderlich sind, werden Datenbankseiten früher als erforderlich gefüllt, und es wird sogar Speicherplatz verschwendet, wenn die Zeilengröße so gewählt ist, dass nicht mehr als ein Datensatz auf der Seite aufgezeichnet werden kann. Das Ergebnis ist, dass mehr Seiten zum Schreiben und Lesen benötigt werden, und dass mehr RAM-Speicher zum Zwischenspeichern verwendet wird (größere Datensätze erfordern mehr Speicher). Und da Ihre Datentypen größer als auf der Festplatte erforderlich angegeben sind, treten bei Ihren Indizes die gleichen Probleme auf - insbesondere, wenn Sie den zusammengesetzten Primärschlüssel mit 2 BIGINT-Spalten gruppieren, da alle anderen erstellten Indizes diesen Primärschlüssel implizit in ihre Definition kopieren.

Wenn Sie wissen, dass einige Spalten in einer Tabelle, die Millionen von Zeilen enthalten, oder sogar eine kleine Tabelle, die mehrere Millionen Zeilen enthält, keine 4-Byte-Ganzzahl zum Speichern ihrer Daten benötigen, sondern 2 Byte ausreichen - verwenden Sie SMALLINT . Wenn Werte im Bereich von 0 bis 255 ausreichen, geben Sie TINYINT ein . Eine Ja / Nein-Flagge? Es gibt BIT .

Fabricio Araujo
quelle
9

Während es bei tinyintvs intdeutliche Unterschiede gibt, wie z. B. Speicherplatz, Seitenteilung und Wartungszeit, würde es für keines von diesen Unterschiede geben varchar.

Warum also nicht alle Textfelder als deklarieren varchar(4000), da es sowieso nur den benötigten Platz verbraucht? Darüber hinaus können Sie sicher sein, dass Ihre Daten niemals abgeschnitten werden.

Die Antwort lautet natürlich:

  1. Klarstellung Ihrer Absichten (da niemand verstehen wird, warum ein Namensfeld 4000 Zeichen enthalten sollte)
  2. Bestätigung, um sicherzustellen, dass niemand eine ganze Biografie als Namen eingibt.

Die gleichen Gründe gelten tinyintauch für.

yoel halb
quelle
3
Dies ist ein älterer Thread, aber Klarstellung und Validierung sind nicht der einzige Grund. Wenn Sie VARCHAR (4000) für etwas haben, das VARCHAR (20) sein sollte, wird der Abfrageplan annehmen, dass Ihre Speicher- und CPU-Anforderungen ein Vielfaches dessen sind, was sie in Bezug auf diese Spalte sein sollten. Ich habe mir nicht die Zeit genommen, dies zu tun, aber ich vermute, dass Sie dies wahrscheinlich sehen können, indem Sie einen Abfrageplan für VARCHAR (20) durchsehen und dann zu VARCHAR (4000) wechseln und die geschätzten Kosten überprüfen.
3
@ GeorgeShouse Demonstration davon hier
Martin Smith