在MySQL中存储CLLocationDegrees时精度会丢失

时间:2013-02-19 03:52:12

标签: mysql ios double core-location precision

我正在开发一个小应用程序,它将iOS设备指定的 Placemarks 存储到MySQL后端。当设备保存新的地标时,会将其插入数据库,并将新生成的ID发送回客户端。如果其他设备尝试保存相同的地标,则服务器需要确定它已存在于数据库中,而不是INSERT并生成新ID,而是需要将其发送回客户端该地标的现有ID。

2 地标如果相同则相同:

  • 名称
  • 纬度
  • 经度

因此,服务器会尝试通过发出

来识别提交的地标是否已存在
  

SELECT id FROM Placemark WHERE name = x,latitude = y,longitude = x

  • 在iOS中,latitude
  • 报告的longitudeCLLocationDegrees为度数,<CoreLocation>latitude类型
  • 在MySQL中,longitudeDOUBLE被定义为latidude


问题:
存储坐标时精度会丢失,例如: 50.09529561485427 50.0952956148543 longitude存储为-122.9893130423316 -122.989313042332 TEXT VARCHAR存储为SELECT placemarks coordinates BETWEEN x AND y

问题:
我可以在MySQL中使用不同的数据类型,以便保存每个坐标吗?

备注:

  • 我无法将坐标存储为{{1}}或{{1}},因为我需要能够说{{1}},或执行其他算术SELECT
  • 我不能使用MySQL的空间扩展,因为可移植性是一个问题,而且因为我的理解,当用作键时空间数据类型非常慢(我的用例需要按坐标选择SELECT)。

任何帮助表示赞赏

2 个答案:

答案 0 :(得分:3)

实际上,进一步的测试揭示了以下奇怪的结果:当数据库驱动程序将数据绑定到查询语句时精度会丢失,而之前数据实际插入数据库中。

这有以下有趣的结果:即使我将键绑定到后续的搜索查询,精度似乎也以相同的方式丢失,因此几乎“偶然”返回正确的结果。也就是说,键(坐标)存储不正确,然后后续选择也错误地转换查询键,但是以匹配的方式,因此找到记录。鉴于由于精度损失导致的转换总是在同一平台(服务器)上执行,因此可能会安全地离开?或者可能不是,也许未来的迁移练习(即,由于缩放)将使舍入误差明显。

Yawar的指针引导我阅读MySQL的手册,该手册解释了浮点数可以在不损失精度的情况下存储为DECIMAL:

“精确值数字文字具有整数部分或小数部分,或两者兼而有之。它们可能已签名” http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html

鉴于现有解决方案似乎有效,问题就变成了,保持数据库数据类型DOUBLE或切换到DECIMAL更好吗?

<强>存储
Latitude的范围为-90 to +90,iOS似乎使用14 decimals的精度 Longitude的范围为-180 to +180,在iOS上保留13 decimals的精度

这意味着我们需要:
LatitudeDECIMAL(16,14),占用较少的8个字节的存储空间(每个包9个字节为4个字节)
LongitudeDECIMAL(16,13),还需要少于8个字节的存储空间

相反,DOUBLE类型的列需要8个字节的存储空间。

速度(算术):
浮点运算几乎总是更快,因为它本身由硬件支持

速度(搜索):
我认为DECIMAL索引与DOUBLE索引具有非常相似的运行时间。

<强>结论:
切换到DECIMAL可以消除精度错误并降低存储要求,但算术性能损失在此用例中可以忽略不计。

答案 1 :(得分:0)

不是将纬度和经度存储为double,乘以1000000,转换为整数,然后存储它。当然,如果您需要在应用程序中阅读它们,则除以1000000.0。

这将为地标提供足够的精度(0.000001º),并将消除您所拥有的浮点转换和精度问题,并占用更少的空间。我在我自己的数据中使用它(它是二进制文件,而不是SQL)并称之为MicroDegrees。