实际上进一步的测试揭示了以下奇怪的结果:当数据库驱动程序将数据绑定到查询语句时,以及在数据实际插入数据库之前,精度就丢失了。
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.