Search code examples
javabigdatastoragecurrencybigdecimal

Storing a large number of money totals and memory/storage implications - BigDecimal vs Integer and best practices?


The BigDecimal class is the standard way of dealing with monetary units in Java. However, when storing extremely large quantities of data (think millions ~ billions of entries per user) the extra storage space must be considered when compared to primitives such as int: according to this answer a single BigDecimal corresponds to about 36 + Ceiling(log2(n)/8.0) bytes (not including some metadata descriptors and such) whereas an int is most usually 4 bytes.

When storing millions of entries, this would of course result in a very noticeable increase in not only memory usage but also storage space (e.g. using MongoDB with a descriptor of the type, or the PostgreSQL numeric type which seems to correspond to at least 8 bytes, I am not familiar with e.g. Cassandra so I am not sure what the storage implications there would be).

An alternative to using the BigDecimal type would be be to store the integer amount of cents (or whatever the smallest denomination is chosen to be, i.e. $1 == 10000 hundredths of a cent, as required for precision). This would not only reduce the strain on the program but also reduce the storage required for all but the greatest values in the dataset (which would be outliers anyway and will likely need to be handled separately).

Is this a viable alternative? Are there any pitfalls that must be avoided in this case? Is this approach compliant with current standards (e.g. external audit)?

Note: This only pertains to storing the data, the data would still be displayed with proper formatting to the user depending on various factors (i.e. Locale, e.g. $31,383.22 for US).


Solution

    • On the database side DECIMAL poses no problem (maybe in the NOSQL databases though).
    • On the java side BigDecimal is no problem too, if you do not keep mass data in memory. Also mind, BigDecimal for normal numbers, in the int-range, is comparable with a String. Those are acceptable small objects, java can deal well with.

    Cents is feasible, but one does not entirely escape BigDecimal. Financial calculations like taxes are in most countries required in some precision, like 6 decimals. Also the standard java components do not provide a "virtual" decimal point. From standard output/input, JSF, to JasperReports etcetera.

    It should be mentioned that BigDecimal usage is verbose too.

    So I would start with BigDecimal, to get a working system fast, and only on massive "spreadsheet" work revert to Cents.