Actually further testing revealed the following curious outcome: the precision is lost when the DB driver binds the data to the query statement, and before the data is actually inserted into the DB.
This has the following interesting consequence: The precision seems to be lost in an identical manner even when I bind keys to my subsequent search queries, and therefore almost "accidentally" the correct result is returned. That is, the key (coordinates) is stored incorrectly, and then subsequent selects also convert query keys incorrectly, but in a matching manner, and therefore the record is found. Given that the conversions due to precision loss are always performed on the same platform (the server), it's probably safe to leave as is?? Or maybe not, perhaps a future migration exercise (i.e., due to scaling) will make the rounding errors apparent.
Yawar's pointer led me to MySQL's manual which explains that floating point numbers can be stored without loss of precision as DECIMAL:
"Exact-value numeric literals have an integer part or fractional part, or both. They may be signed" http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html
Given that the existing solution seems to work, the question then becomes, is it better to keep the DB data type DOUBLE
, or switch to DECIMAL
?
Storage:
Latitude
has range from -90 to +90
, and iOS seems to use precision of 14 decimals
Longitude
has range from -180 to +180
, which leaves precision of 13 decimals
on iOS
That means we need:
Latitude
: DECIMAL(16,14)
, which takes less the 8 bytes of storage (4 bytes for each pack of 9d)
Longitude
: DECIMAL(16,13)
, also requiring less than 8 bytes of storage
In contrast, a column of type DOUBLE
requires 8 bytes of storage.
Speed (arithmetic):
Floating point arithmetic will almost always be materially faster because it is supported natively by the hardware
Speed (searches):
I believe index of DECIMAL
vs index of DOUBLE
have a very comparable runtime.
Conclusion:
Switching to DECIMAL
eliminates the precision errors and also reduces storage requirements, at an arithmetic performance penalty which is negligible in this use case.