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

时间:2008-10-01 19:18:14

标签: mysql database-design maps mapping latitude-longitude

请记住,我将在lat / long对上执行计算,哪种数据类型最适合与MySQL数据库一起使用?

22 个答案:

答案 0 :(得分:154)

将MySQL的spatial extensions与GIS结合使用。

答案 1 :(得分:146)

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

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

答案 2 :(得分:114)

基本上,这取决于您所在位置所需的精度。使用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

希望这有帮助。

答案 3 :(得分:74)

MySQL的Spatial Extensions是最佳选择,因为您可以使用空间运算符和索引的完整列表。空间索引将允许您非常快速地执行基于距离的计算。请记住,从6.0开始,Spatial Extension仍然不完整。我没有放下MySQL Spatial,只是在你走得太远之前让你知道陷阱。

如果您严格处理积分并且只处理DISTANCE功能,那么这很好。如果需要使用“多边形”,“线”或“缓冲点”进行任何计算,则除非使用“关联”运算符,否则空间运算符不会提供精确结果。请参阅21.5.6顶部的警告。包含,内部或相交等关系使用MBR,而不是精确的几何形状(即椭圆被视为矩形)。

此外,MySQL Spatial中的距离与第一个几何体的距离相同。这意味着如果您使用十进制度数,则您的距离测量值为十进制度数。这将使你很难得到准确的结果,因为你从赤道得到了更好的结果。

答案 4 :(得分:70)

当我为ARINC424构建的导航数据库执行此操作时,我进行了大量测试并回顾了代码,我使用了DECIMAL(18,12)(实际上是NUMERIC(18,12),因为它是firebird )。

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

关键是当使用度数或弧度时,我们知道值的范围 - 而小数部分需要最多的数字。

MySQL Spatial Extensions是一个不错的选择,因为它们遵循The OpenGIS Geometry Model。我没有使用它们,因为我需要保持数据库的可移植性。

答案 5 :(得分:37)

取决于您所需的精确度。

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
  • 使用的最常见类型是DECIMAL(8,6)/(9,6)

MySQL 5.7开始,请考虑使用Spatial Data Types(SDT),特别是POINT来存储单个坐标。在5.7之前,SDT不支持索引(当表类型为MyISAM时,5.6除外)。

注意:

答案 6 :(得分:32)

基于这篇wiki文章 http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy MySQL中适当的数据类型是Decimal(9,6),用于存储经度和纬度 单独的领域。

答案 7 :(得分:19)

使用DECIMAL(8,6)表示纬度(90至-90度),DECIMAL(9,6)表示经度(180至-180度)。对于大多数应用程序,小数点后6位。两者都应该“签名”以允许负值。

答案 8 :(得分:13)

根据谷歌地图的说法,没有必要走得太远,对于lat和lng,最好的是FLOAT(10,6)。

答案 9 :(得分:7)

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

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

答案 10 :(得分:6)

以完全不同且更简单的方式:

通过这种方式,您无需担心索引编号以及与数据类型相关的所有其他问题,这些问题可能会破坏您的坐标。

答案 11 :(得分:4)

虽然它不是所有操作的最佳选择,但是如果你制作地图图块或使用大量标记(点)只有一个投影(例如墨卡托,就像谷歌地图和许多其他滑动地图框架所期望的那样),我我发现我所谓的“Vast Coordinate System”真的非常方便。基本上,你以某种方式存储x和y像素坐标 - 放大 - 我使用缩放级别23.这有几个好处:

  • 您只需执行一次昂贵的lat / lng到mercator像素转换,而不是每次处理该点
  • 从给定缩放级别的记录中获取切片坐标需要右移一次。
  • 从记录中获取像素坐标需要一个右移和一个按位AND。
  • 转换非常轻巧,在SQL中实现它们是切实可行的,这意味着您可以执行DISTINCT,每个像素位置只返回一条记录,这将减少后端返回的数字记录,这意味着更少在前端处理。

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

答案 12 :(得分:4)

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

为什么有人愿意自愿“预先降低”精确度,然后再对较差的数字进行计算?听起来最愚蠢。

如果源具有64位精度,那么自愿将比例缩小到例如,这肯定是愚蠢的。 6个小数,并将精度限制为最多9个重要的挖掘(通常建议的十进制9.6格式)。

当然,人们以源材料的精度存储数据。降低精度的唯一原因是存储空间有限。

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

十进制9.6格式会导致对齐网格现象。如果它发生的话,这应该是最后一步。

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

答案 13 :(得分:4)

MySQL对所有浮点数使用double ... 所以使用double类型。在大多数情况下使用float会导致不可预测的舍入值

答案 14 :(得分:4)

答案 15 :(得分:3)

PostGIS中的空间函数比MySQL空间函数中的空间函数功能更强大(即不受BBOX操作限制)。看看:link text

答案 16 :(得分:2)

TL; DR

如果您不是在NASA /军方工作,也不是在制造飞机的导航系统,请使用FLOAT(8,5)。


要完全回答您的问题,您需要考虑以下几点:

格式

  • 度分秒:40°26′46″ N 79°58′56″ W
  • 度十进制分钟数:40°26.767′N 79°58.933′W
  • 小数1度:40.446°N 79.982°W
  • 十进制2 :-32.60875,21.27812
  • 其他一些自制格式?没有人禁止您创建自己的以居家为中心的坐标系,并将其存储为朝向和离家的距离。对于您正在处理的某些特定问题,这可能很有意义。

所以答案的第一部分将是-您可以将坐标存储为应用程序使用的格式,以避免来回不断的转换并简化SQL查询。

很可能您使用Google Maps或OSM来显示数据,而GMaps使用的是“十进制2”格式。因此,以相同的格式存储坐标会更加容易。

精度

然后,您想定义所需的精度。当然,您可以存储“ -32.608697550570334,21.278081997935146”之类的坐标,但是在导航到该点时您是否关心过毫米?如果您不是在NASA工作,也不在做卫星,火箭或飞机的轨迹,则精度应达到几米。

常用的格式是点后5位,这使您的精度达到50cm。

示例:X,21.278081 8 与X,21.278081 9 之间有1cm的距离。因此,点后7位数字可为您提供1 / 2cm的精度,点后5位数字将为您提供1/2米的精度(因为不同点之间的最小距离为1m,因此舍入误差不能超过其一半)。对于大多数民用目的来说,就足够了。

十进制小数分钟格式(40°26.767′N 79°58.933′W)为您提供与点后5位数字完全相同的精度

节省空间的存储

如果您选择了十进制格式,则坐标为一对(-32.60875,21.27812)。显然,2 x(1位用于符号,2位用于度数,5位用于指数)就足够了。

因此,在这里,我想从评论中支持 Alix Axel ,说Google建议将其存储在FLOAT(10,6)中确实是多余的,因为您不需要4位数字来表示部分(因为符号被分隔并且纬度限制为90,经度限制为180)。您可以轻松地将FLOAT(8,5)用于1 / 2m精度,或者将FLOAT(9,6)用于50 / 2cm精度。或者甚至可以将lat和long存储在单独的类型中,因为FLOAT(7,5)对于lat就足够了。请参见MySQL浮点类型reference。它们中的任何一个都将像普通的FLOAT一样,并且等于4个字节。

通常,如今空间不再是问题,但是如果出于某种原因要真正优化存储(免责声明:请勿进行预优化),则可以压缩lat(不超过91 000个值+符号)+长(不超过181 000个值+符号)到21位,比2xFLOAT(8个字节== 64位)少得多

答案 17 :(得分:1)

  1. 纬度范围为-90至+90(度),因此可以使用DECIMAL(10,8)

  2. 经度的范围是-180到+180(度),因此您需要DECIMAL(11,8)。

注意:第一个数字是存储的总位数,第二个数字是小数点后的数字。

简而言之:lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL

答案 18 :(得分:0)

用于存储纬度长值的理想数据类型是十进制(9,6)

这大约是10厘米的精度,而仅使用5个字节的存储空间。

例如CAST(123.456789为十进制(9,6))

答案 19 :(得分:0)

我建议您将Float数据类型用于SQL Server。

答案 20 :(得分:-2)

Lat Long计算需要精度,因此请使用某种类型的十进制类型,并使精度至少比存储的数字高2,以便执行数学计算。我不知道我的sql数据类型,但在SQL服务器中,人们经常使用float或real而不是decimal,并且遇到麻烦,因为这些是估计的数字而不是真正的数字。因此,只需确保您使用的数据类型是真正的十进制类型而不是浮动十进制类型,您应该没问题。

答案 21 :(得分:-4)

FLOAT应该为您提供所需的所有精度,并且比将每个坐标存储为字符串等更适合比较函数。

如果你的MySQL版本早于5.0.3,你可能需要注意某些floating point comparison errors

  

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

相关问题