Float vs. Decimal
Giorni fa mi sono ritrovato a dover creare una tabella con un campo destinato a contenere un valore numerico a due cifre decimali, il peso in kg dei prodotti di magazzino. Sono sorti dunque i seguenti dilemmi: devo usare un tipo di dato float o decimal? Quali differenze ci sono tra i due tipi di dato?
Innanzi tutto, mi sono documentato sui BOL ed ho trovato le differenze sostanziali:
- il float è un tipo di dato numerico approssimato, mentre il decimal è a scala e precisione fisse (dove per precisione s’intende il numero totale di cifre componenti il numero, comprese le cifre dopo la virgola; per scala s’intende il numero di cifre dopo la virgola)
- differenze nel range e nella occupazione:
| float(1..24) = float(24) (real) | (-3.40E+38..-1.18E- 38), 0, (1.18E-38..3.40E+38) | 4 byte |
| float(25..53) = float(53) (double precision) | (-1.79E+308..-2.23E-308), 0, (2.23E-308..1.79E+308) | 8 byte |
| decimal(p=1..9, s) | -10^p +1 .. 10^p - 1 | 5 byte |
| decimal(p=10..19, s) | -10^p +1 .. 10^p - 1 | 9 byte |
| decimal(p=20..28, s) | -10^p +1 .. 10^p - 1 | 13 byte |
| decimal(p=29..38, s) | -10^p +1 .. 10^p - 1 | 17 byte |
Essendo dunque il float un tipo di dato a virgola mobile, è evidente che è indicato per calcoli scientifici con molte cifre decimali, dove una approssimazione di queste ultime è ammessa. E’ altresì evidente che per calcoli finanziari, ad esempio, non sono ammesse tali approssimazioni e di qui il necessario utilizzo di un tipo di dato a scala e precisione fisse.
Nel mio caso, il numero più grande che avrei potuto rappresentare era del tipo xx.xxx.xxx,yy. Quindi, usando un tipo a precisione fissa, avrei dovuto utilizzare il decimal(10,2), con una occupazione di 9 byte, contro i 4 byte del float(24).
Pertanto mi sono chiesto se in effetti era necessario avere una precisione fissa per la casistica che dovevo risolvere: fornire una reportistica completa per il management aziendale sulle operazioni e le grandezze di magazzino. Confontandomi con i destinatari del lavoro, siamo giunti alla conclusione che una precisione “al capello” non era affatto necessaria, poiché la lettura del report avrebbe dovuto dare un’idea di massima delle grandezze che si andavano a rappresentare. Quindi con mio sommo gaudio :) mi sono sentito tranquillo nell’utilizzare il float(24) e dunque risparmiare ben 5 byte di spazio per ogni numero persistito!
Ma non sempre la ruota della fortuna gira dalla tua parte! Il database gestionale della stessa azienda tratta tutti i dati numerici come decimal(x,y) (l’età di una persona è un decimal(3,0)!! Ah, quanto avrei voluto vedere un bel tinyint!!). Nello stesso database ci sono, inoltre, parecchi campi numerici (sempre decimal, ovviamente) che contengono tanti zeri o valori interi! Certamente, in questi casi, lo spreco di byte è incommensurabile!! Dunque mi sono chiesto se fosse esistito un tipo di dato simile al varchar che avrebbe potuto risolvere il problema… Ho scoperto che dal Service Pack 2 di SQL Server 2005 (solo edizioni Enterprise, Developer ed Evaluation) è stato reso disponibile il formato di memorizzazione (e non un tipo di dato) vardecimal. Ho pensato dunque di aver trovato un escamotage al problema. Ma non appena ho aperto i BOL sull’argomento ho trovato questo:
This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use ROW and PAGE compression instead. For more information, see Creating Compressed Tables and Indexes.
Cavoli! Per un momento avevo pensato di aver risolto il problema con un “barbatrucco” (termine preso in prestito da un famoso cartoon della mia infanzia, che qualcuno ricorderà benissimo :) ). Ora mi ritrovo a dover studiare un nuovo argomento: la compressione dei dati! Sicuramente sarà questo uno dei temi dei prossimi post :P
A voi è già capitato di dover affrontare un problema del genere? Preziosi suggerimenti sono ben accetti!! :)