SQL Server Decimal (9, 0) vs INT

15

Einer unserer Kunden verwendet für einige Spalten den Datentyp DECIMAL(18,0)in seiner SQL Server 2008R2-Datenbank. Da die Spalten relativ langsam wachsen, schlug er kürzlich vor, den Datentyp zu ändern DECIMAL(5,0), um Speicherplatz freizugeben .

Entsprechend der MSDN-BibliothekDECIMAL(5,0) beträgt der Speicherplatz des Datentyps genau wie der DECIMAL(9,0)Datentyp 5 Byte. INTist 1 Byte kleiner, kann aber alles im Bereich von -2 ^ 31 bis 2 ^ 31 statt der -99.999 bis 99.999 DECIMAL(5,0)speichern, die gespeichert werden können. Sogar die größte, DECIMALdie in 5 Bytes ( DECIMAL(9,0)) passt, kann nur Ganzzahlen im Bereich von -999.999.999 bis 999.999.999 (was weniger als der Hälfte des Bereichs entspricht, INTder in 4 Bytes angeboten wird) speichern .

Ich kann mich zwei „Vorteile“ der Verwendung von DECIMALmehr als INT:

  • Die Möglichkeit, nachträglich Skalierungen vorzunehmen, ohne mehr Speicherplatz zu benötigen
  • Die Möglichkeit, die Genauigkeit auf 38 Stellen zu skalieren, ohne den Datentyp zu ändern

aber das sind meiner meinung nach keine wirklichen vorteile:

  • Das Hinzufügen einer Skalierung zu Ganzzahlen ist nur in wenigen Fällen sinnvoll (in den meisten Fällen, in denen eine Skalierung einen Unterschied macht, kann sie auch vorher hinzugefügt werden).
  • SQL Server betrachtet jede Genauigkeits- / Skalierungskombination als einen anderen Datentyp, sodass der Datentyp beim Erhöhen der Genauigkeit oder Skalierung nicht allein gelassen wird.

Ich frage mich daher: Was ist der zusätzliche Vorteil eines DECIMAL(5,0)Datentyps für Ganzzahlen?

vstrien
quelle
1
Ein Vorteil kann das fünfstellige Limit sein. Aber ich frage mich, wie viel Speicherplatz Sie mit einer solchen Änderung sparen können.
Dezso
3
IMO, wenn Sie nur sicherstellen müssen, dass die Spaltenwerte innerhalb eines Bereichs liegen, verwenden Sie eine Prüfbedingung. Ich denke, die einzige Überlegung hier wäre, wenn es die Möglichkeit gibt, dass diese Spalte in Zukunft gebrochene Werte erfordert.
Jon Seigel
3
Wenn sie sich Sorgen um Speicherplatz machen, sind sie besser für die Komprimierung geeignet. Die Verwendung von Dezimal (x, 0) anstelle von int / bigint bietet keinen greifbaren Vorteil.
Robert L Davis
7
Ein weiterer Unterschied zwischen decimal(x,0)und einem Integer-Typ zeigt sich in der arithmetischen Division. Wenn Sie ein Int durch ein Int teilen, erhalten Sie ein Int. Wenn Sie eine Dezimalzahl (x, 0) durch ein Int dividieren, erhalten Sie eine Dezimalzahl (x + 6,6).
Andriy M
@AndriyM, ich denke das ist der größte Vorteil. Formuliere es in eine Antwort anstatt in einen Kommentar und ich markiere es als Antwort.
Vstrien

Antworten:

8

Ich bin damit einverstanden, dass es in Bezug auf die Lagerung keine wirklichen Vorteile gibt gibt, solange Sie DECIMAL (9, 0) mit INT oder DECIMAL (18, 0) mit BIGINT vergleichen. (Innerhalb eines einzelnen Bytes.)

In Bezug auf die Verarbeitung, wie @Andriy sagt, teilt sich das DECIMAL natürlich in einen Typ auf, der den Bruchteil nicht verliert, wenn das für Sie wichtig ist.

Auf der anderen Seite ist die Arbeit mit nativen INT-Typen vom numerischen Standpunkt aus viel schneller, wenn Sie eine Vielzahl von SUM () - oder Vergleichsoperationen ausführen (z. B. die Suche nach Werten), da diese von der CPU effizienter weitergeleitet werden. Ein int-Vergleich besteht aus zwei Assembly-Opcodes (MOV, CMP), aber jeder Dezimalvergleich ist um ein Vielfaches größer.

Chris Chubb
quelle
Ihre Antwort ist sinnvoll, aber ein Prozessor hat keine Kenntnisse über Datentypen. Ein Datentyp von 4 Bytes wird also genauso schnell verglichen wie ein anderer Datentyp von 4 Bytes. Können Sie (z. B. mit einem wiederholbaren Leistungstest) zeigen, dass die Verwendung von DECIMAL(9, 0)anstelle von einen Leistungstest ein Leistungshit ist INT?
Vstrien
2
Ich dachte, ich könnte, aber ich gebe zu, dass meine Tests nicht schlüssig sind. Möglicherweise führt SQL eine Optimierung durch, um das Problem auf Ganzzahlen zu reduzieren. Mein Testbed: `--Int Vergleich SET @StartTime = SYSDATETIME () WHILE (@CounterINT <@SizeINT) SET @CounterINT = @CounterINT + 1 PRINT 'INT nahm' + CONVERT (VARCHAR (20), DATEDIFF (Millisekunde, @StartTime , SYSDATETIME ())) + 'milliseconds' --Decimal SET @StartTime = SYSDATETIME () WHILE (@CounterDEC <@SizeDEC) SET @CounterDEC = @CounterDEC + 1 PRINT 'DEC taken' + CONVERT (VARCHAR (20), DATEDIFF (Millisekunde, @StartTime, SYSDATETIME ()) + 'Millisekunden' `
Chris Chubb
Ich denke, SQL Server optimiert dort tatsächlich etwas. Trotz der Optimierung DECIMALdauert das meist noch etwas länger (zumindest auf meinem Entwicklungssystem). In einem Durchlauf von 10 Tests um 51 ms DEC gegenüber 46 ms INT.
Vstrien
2

Es sieht so aus, als gäbe es keine Vorteile hinsichtlich des Speicherplatzes.

Wenn Ihr Client befürchtet, dass Ihre Werte größer als 2 ^ 32-1 sind (maximaler positiver Wert, den eine Ganzzahl speichern kann), sollten Sie in Betracht ziehen, auf BigInt umzusteigen - mit 64 Bit ( 8 Byte) .

AlexTheDeveloper
quelle