在MySQL数据库中存储纬度/经度时使用的理想数据types是什么?

考虑到我将对经纬度对进行计算,哪种数据types最适合用于MySQL数据库?

使用MySQL的空间扩展与GIS。

Google为使用Google地图的示例“商店定位器”应用程序提供了一个开始完成PHP / MySQL解决scheme的过程。 在这个例子中,他们将lat / lng值存储为长度为“10,6”的“Float”

http://code.google.com/apis/maps/articles/phpsqlsearch.html

基本上这取决于你的位置所需的精度。 使用DOUBLE你将有一个3.5nm的精度。 DECIMAL(8,6)/(9,6)下降到16cm。 FLOAT是1.7米…

这个非常有趣的表格有一个更完整的列表: http : //mysql.rjweb.org/doc.php/latlng :

 Datatype Bytes Resolution Deg*100 (SMALLINT) 4 1570 m 1.0 mi Cities DECIMAL(4,2)/(5,2) 5 1570 m 1.0 mi Cities SMALLINT scaled 4 682 m 0.4 mi Cities Deg*10000 (MEDIUMINT) 6 16 m 52 ft Houses/Businesses DECIMAL(6,4)/(7,4) 7 16 m 52 ft Houses/Businesses MEDIUMINT scaled 6 2.7 m 8.8 ft FLOAT 8 1.7 m 5.6 ft DECIMAL(8,6)/(9,6) 9 16cm 1/2 ft Friends in a mall Deg*10000000 (INT) 8 16mm 5/8 in Marbles DOUBLE 16 3.5nm ... Fleas on a dog 

希望这可以帮助。

MySQL的空间扩展是最好的select,因为您可以使用空间运算符和索引的完整列表。 空间索引将允许您非常快速地执行基于距离的计算。 请记住,从6.0开始,Spatial Extension仍然不完整。 我不会放下MySQL Spatial,只是让你知道这个陷阱之前,你太过分了。

如果你严格地处理分数和只有DISTANCEfunction,这是没有问题的。 如果您需要使用多边形,线条或缓冲点进行任何计算,则空间运算符不会提供确切的结果,除非使用“相关”运算符。 请参阅21.5.6顶部的警告 。 诸如包含,相交或相交之类的关系使用MBR,而不是确切的几何形状(即椭圆被视为矩形)。

此外,MySQL Spatial中的距离与第一个几何体的单位相同。 这意味着如果您使用十进制度数,那么您的距离测量值是十进制度数。 这将使你很难从赤道上空获得确切的结果。

当我用ARINC424构build的导航数据库的时候,我做了大量的testing并回顾了代码,我使用了DECIMAL(18,12)(实际上是一个NUMERIC(18,12),因为它是firebird)。

浮动和双打不精确,可能会导致舍入错误,这可能是一个非常糟糕的事情。 我不记得我是否发现了任何有问题的真实数据 – 但是我相当确定,无法准确存储在浮点数或双精度数中可能会导致问题

重点是,当使用度或弧度时,我们知道值的范围 – 小数部分需要最多的数字。

MySQL Spatial Extensions是一个很好的select,因为它们遵循OpenGIS几何模型 。 我没有使用它们,因为我需要保持我的数据库的便携性。

根据这篇wiki文章http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy ,在MySQL中适当的数据types是十进制(9,6),用于在单独的字段中存储经度和纬度。

取决于你需要的精度。

 Datatype Bytes resolution ------------------ ----- -------------------------------- Deg*100 (SMALLINT) 4 1570 m 1.0 mi Cities DECIMAL(4,2)/(5,2) 5 1570 m 1.0 mi Cities SMALLINT scaled 4 682 m 0.4 mi Cities Deg*10000 (MEDIUMINT) 6 16 m 52 ft Houses/Businesses DECIMAL(6,4)/(7,4) 7 16 m 52 ft Houses/Businesses MEDIUMINT scaled 6 2.7 m 8.8 ft FLOAT 8 1.7 m 5.6 ft DECIMAL(8,6)/(9,6) 9 16cm 1/2 ft Friends in a mall Deg*10000000 (INT) 8 16mm 5/8 in Marbles DOUBLE 16 3.5nm ... Fleas on a dog 

来自: http : //mysql.rjweb.org/doc.php/latlng

总结:

  • 最精确的可用选项是DOUBLE
  • 使用的最常见的types是DECIMAL(8,6)/(9,6)

从MySQL 5.7开始 ,请考虑使用空间数据types (SDT),特别是用于存储单个坐标的POINT 。 在5.7之前,SDT不支持索引(当表types是MyISAM时5.6除外)。

注意:

  • 使用POINT类时,存储坐标参数的顺序必须是POINT(latitude, longitude)
  • 有一个特殊的语法来创build一个空间索引 。
  • 使用SDT的最大好处是可以访问空间分析函数 ,例如计算两点之间的距离( ST_Distance )并确定一个点是否包含在另一个区域( ST_Contains )中。

对于纬度(90到-90度)使用DECIMAL(8,6) ,对于经度(180到-180度)使用DECIMAL(9,6) )。 小数点后6位适用于大多数应用。 两者都应该“签字”以允许负面价值。

根据谷歌地图,没有必要走得太远,最好的是经纬度(10,6)。

我们将oracle数据库中的纬度/经度X 1,000,000存储为NUMBERS,以避免双击错误。

鉴于到小数点后6位的经纬度是10厘米的精度,那就是我们所需要的。 许多其他数据库也存储经纬度到小数点后六位。

在一个完全不同的和更简单的angular度来看:

  • 如果您依靠Google来显示您的地图,标记,多边形等等,那么让Google来完成计算!
  • 你可以节省资源在你的服务器上,你只需要把经度和纬度作为一个单一的string( VARCHAR )一起存储,例如:“- 0000.0000001,-0000.000000000000001 ”(长度为35,如果一个数字多于7个十进制数字, ;
  • 如果Google返回每个数字7位以上的十进制数字,则无论如何都可以将该数据存储在string中,以防万一您想要检测未来的某些逃离或微生物 ;
  • 您可以使用它们的距离matrix或它们的几何库来计算特定区域中的距离或检测点 ,调用如此简单: google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • 有许多使用Google Maps API的“服务器端”API(在Python , Ruby on Rails , PHP , CodeIgniter , Laravel , Yii , Zend Framework等)。

这样,您就不必担心索引编号以及所有与数据types相关的其他问题,这些问题可能会影响您的坐标。

取决于你的应用程序,我build议使用FLOAT(9,6)

空间键会给你更多的function,但是在生产基准testing中浮点数比空间键要快得多。 (AVG中0,01 VS 0,001)

虽然对于所有的操作来说都不是最佳的,但是如果你正在制作地图块或者只用一个投影(例如墨卡托,像谷歌地图和许多其他的滑动地图框架所期望的那样)来处理大量的标记(点),我已经find了什么我称之为“Vast Coordinate System”真的很方便。 基本上,你以某种方式存储x和y像素坐标放大 – 我使用缩放级别23.这有几个好处:

  • 你做一次昂贵的lat / lng到mercator像素转换,而不是每次处理点
  • 从给定缩放级别的logging获取瓦片坐标需要一个右移。
  • 从logging获取像素坐标需要一个右移和一个按位AND。
  • 这些转换是如此轻量级以至于在SQL中执行它们是实际的,这意味着您可以执行DISTINCT来仅返回每个像素位置的一条logging,这将减less后端返回的数量logging,这意味着更less的处理前端。

我在最近的博客文章中谈到了这一切: http : //blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/

PostGIS中的空间函数比MySQL空间函数中的空间函数function更强大(即不受BBOX操作的限制)。 检查出来: 链接文本

我对一些答复/评论感到非常惊讶。

为什么人们愿意自愿“预先减less”精度,然后再对更差的数字进行计算? 听起来最终是愚蠢的。

如果源代码具有64位的精度,肯定会自动将这个尺度固定到例如。 6位小数,并且将精度限制为最多9个重要的挖掘点(这与通常提出的十进制9.6格式一致)。

当然,用源材料所具有的精度来存储数据。 降低精度的唯一原因是存储空间有限。

  • 以原始准确度存储源数字
  • 在计算发生的精度中存储从源计算的数字(例如,如果应用程序代码使用双精度,则将结果存储为双精度)

十进制的9.6格式会导致一个单元格到现象。 这应该是最后一步,如果一切都发生的话。

我不会邀请累积的错误到我的巢。

MySQL对所有的浮点数使用double …所以使用doubletypes。 在大多数情况下使用float将导致不可预知的舍入值

一个FLOAT应该给你所有你需要的精度,而且比比较function更好,而不是把每个坐标存储成一个string或类似的东西。

如果您的MySQL版本早于5.0.3,则可能需要注意某些浮点比较错误 。

在MySQL 5.0.3之前,DECIMAL列以精确的精度存储值,因为它们表示为string,但DECIMAL值的计算是使用浮点操作完成的。 从5.0.3开始,MySQL执行DECIMAL操作,精度为64位十进制数字,这应该解决DECIMAL列中最常见的不准确性问题

Lat Long计算需要精确度,所以使用某种types的小数types,并且要使精度至less比您要存储的数字高2以执行math计算。 我不知道我的SQL数据types,但在SQL服务器中,人们经常使用浮点数或实数而不是小数点,因为这些数字估计不是真正的数字。 所以只要确保你使用的数据types是一个真正的十进制types,而不是浮点十进制types,你应该没问题。