Decimale di SQL Server (9, 0) vs INT


15

Uno dei nostri clienti utilizza per alcune colonne il tipo DECIMAL(18,0)di dati nel suo database SQL Server 2008R2. Poiché le colonne crescono abbastanza lentamente, ha recentemente proposto di modificare il tipo di dati in DECIMAL(5,0)per recuperare spazio di archiviazione.

Secondo la libreria MSDN , lo spazio di archiviazione del DECIMAL(5,0)tipo di dati è, proprio come il DECIMAL(9,0)tipo di dati, 5 byte. INTè più piccolo di 1 byte, ma può memorizzare tutto nell'intervallo compreso tra -2 ^ 31 e 2 ^ 31 anziché tra -99.999 e 99.999 che DECIMAL(5,0)può memorizzare. Anche il più grande DECIMALche si inserisce in 5 byte ( DECIMAL(9,0)) può memorizzare solo numeri interi compresi tra -999.999.999 e 999.999.999 (che è meno della metà dell'intervallo INTofferto in 4 byte).

Posso pensare a due "vantaggi" dell'uso di DECIMALover INT:

  • La possibilità di aggiungere successivamente la scala, senza utilizzare più spazio di archiviazione
  • La possibilità di ridimensionare la precisione fino a 38 cifre, senza alterare il tipo di dati

ma questi non sono vantaggi reali secondo me:

  • L'aggiunta di scala a numeri interi ha senso solo in pochissimi casi (nella maggior parte dei casi in cui la scala fa la differenza, potrebbe anche essere aggiunta in anticipo)
  • SQL Server vede ogni combinazione precisione / scala come un diverso tipo di dati, quindi il tipo di dati non viene lasciato solo quando si aumenta la precisione o la scala.

Questo mi fa meravigliare: qual è il vantaggio aggiunto di un DECIMAL(5,0)tipo di dati per numeri interi?


1
Un vantaggio può essere il limite di cinque cifre. Ma mi chiedo quanto spazio di archiviazione puoi risparmiare con un tale cambiamento.
dezso,

3
IMO, se devi solo assicurarti che i valori della colonna rientrino in un intervallo, usa un vincolo di controllo. Penso che l'unica considerazione qui sarebbe se ci fosse la possibilità che questa colonna richiedesse valori frazionari in futuro.
Jon Seigel,

3
Se sono preoccupati per lo spazio di archiviazione, sono più adatti a utilizzare la compressione di questo. Non vi è alcun vantaggio tangibile nell'uso di decimale (x, 0) invece di int / bigint.
Robert L Davis,

7
Un'altra differenza tra decimal(x,0)e un tipo intero si mostra nella divisione aritmetica. Se dividi un int per un int, ottieni un int. Se si divide un decimale (x, 0) per un int, si ottiene un decimale (x + 6,6).
Andriy M,

@AndriyM, penso che questo sia il massimo beneficio. Sostituiscilo in una risposta anziché in un commento e lo segnerò come risposta.
vstrien,

Risposte:


8

Concordo sul fatto che non ci sono vantaggi reali in termini di spazio di archiviazione purché si confrontino DECIMAL (9, 0) vs INT o DECIMAL (18, 0) vs BIGINT. (All'interno di un singolo byte.)

In termini di elaborazione, come dice @Andriy, DECIMAL si divide naturalmente in un tipo che non perde la parte frazionaria, se questo è importante per te.

D'altra parte, lavorare con tipi INT nativi è molto più veloce da un punto di vista numerico se si eseguono molti SUM () o confronti (come la ricerca dei valori) in quanto vengono pipeline in modo più efficiente dalla CPU. Un confronto int è costituito da due codici operativi di assieme (MOV, CMP) ma qualsiasi confronto decimale sarà molti, molti di più.


La tua risposta ha un senso, ma un processore non ha alcuna conoscenza dei tipi di dati. Quindi un tipo di dati di 4 byte viene confrontato con la stessa velocità di un altro tipo di dati di 4 byte. Puoi mostrare (con un test delle prestazioni ripetibile, ad esempio) che c'è un impatto sulle prestazioni nell'uso DECIMAL(9, 0)invece di un INT?
vstrien,

2
Pensavo di poterlo fare, ma ammetto che i miei test non sono conclusivi. Forse SQL sta facendo un'ottimizzazione per ridurre il problema alla matematica dei numeri interi. Il mio banco di prova: `--In paragone SET @StartTime = SYSDATETIME () WHILE (@CounterINT <@SizeINT) SET @CounterINT = @CounterINT + 1 PRINT 'INT take' + CONVERT (VARCHAR (20), DATEDIFF (millisecond, @StartTime , SYSDATETIME ())) + 'millisecondi' - SET decimale @StartTime = SYSDATETIME () WHILE (@CounterDEC <@SizeDEC) SET @CounterDEC = @CounterDEC + 1 PRINT 'DEC take' + CONVERT (VARCHAR (20), DATEDIFF (millisecondi, @StartTime, SYSDATETIME ())) + 'millisecondi' '
Chris Chubb

Penso che SQL Server ottimizzi davvero qualcosa lì. Nonostante l'ottimizzazione DECIMALrichiede ancora un po 'più di tempo (almeno sul mio sistema di sviluppo). In una serie di 10 test intorno a 51 ms DEC contro 46 ms INT.
vstrien,

2

Sembra che non ci saranno benefici in termini di spazio di archiviazione.

Se il tuo cliente è preoccupato del fatto che i tuoi valori saranno maggiori di 2 ^ 32-1 (il numero intero massimo positivo può memorizzare) allora dovresti considerare di passare a BigInt - con 64 bit ( 8 byte) .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.