What datatype to use when storing latitude and longitude data in SQL databases?
在ANSI SQL兼容数据库中存储纬度或经度数据时,哪种数据类型最合适? 应该
我知道Oracle,MySql和SQL Server已经添加了一些专门用于处理地理数据的特殊数据类型,但我对如何将信息存储在"普通的"SQL数据库中感兴趣。
如果你不习惯精度和比例参数,这里有一个格式字符串visual:
我们使用float,但任何带有6位小数的数字风格也应该有效。
好吧,你问过如何存储纬度/经度,我的答案是:不要,你可以考虑使用WGS 84(欧洲ETRS 89),因为它是地理参考的标准。
但除了那个细节,我在SQL 2008之前的几天使用了用户定义类型,最后包括地理支持。
您可以轻松地将lat / lon十进制数存储在无符号整数字段中,而不是将它们拆分为整数和小数部分,并使用以下转换算法分别存储这些内容:
作为存储的mysql函数:
1 2 3 4 5 | CREATE DEFINER=`r`@`l` FUNCTION `PositionSmallToFloat`(s INT) RETURNS DECIMAL(10,7) DETERMINISTIC RETURN IF( ((s > 0) && (s >> 31)) , (-(0x7FFFFFFF - (s & 0x7FFFFFFF))) / 600000, s / 600000) |
然后回来
1 2 3 4 | CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7)) RETURNS INT(10) DETERMINISTIC RETURN s * 600000 |
这需要存储在unsigned int(10)中,这适用于mysql以及无类型的sqlite。
通过经验,我发现这个工作真的很快,如果你需要的只是存储坐标并检索那些做数学的。
在PHP中这两个函数看起来像
1 2 3 4 5 | FUNCTION LatitudeSmallToFloat($LatitudeSmall){ IF(($LatitudeSmall>0)&&($LatitudeSmall>>31)) $LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1; RETURN (FLOAT)$LatitudeSmall/(FLOAT)600000; } |
又回来了:
1 2 3 4 5 | FUNCTION LatitudeFloatToSmall($LatitudeFloat){ $Latitude=round((FLOAT)$LatitudeFloat*(FLOAT)600000); IF($Latitude<0) $Latitude+=0xFFFFFFFF; RETURN $Latitude; } |
这在创建例如具有整数的memcached唯一键方面具有一些额外的优点。 (例如:缓存地理编码结果)。希望这为讨论增添价值。
另一个应用程序可能是当你没有GIS扩展并且只想保留几百万个lat / lon对时,你可以在mysql中的那些字段上使用分区以从它们是整数的事实中受益:
1 2 3 4 5 6 7 8 9 | CREATE TABLE: CREATE TABLE `Locations` ( `lat` INT(10) UNSIGNED NOT NULL, `lon` INT(10) UNSIGNED NOT NULL, `location` text, PRIMARY KEY (`lat`,`lon`) USING BTREE, KEY `index_location` (`locationText`(30)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /*!50100 PARTITION BY KEY () PARTITIONS 100 */ |
在vanilla Oracle中,名为LOCATOR(Spatial的残缺版本)的功能要求使用NUMBER(无精度)数据类型存储坐标数据。当您尝试创建基于函数的索引来支持空间查询时,否则会窒息。
您应该看一下SQL Server 2008中引入的新的Spatial数据类型。它们专门设计了这种任务,使索引和查询数据更加容易和高效。
http://msdn.microsoft.com/en-us/library/bb933876(v=sql.105).aspx
http://blogs.technet.com/andrew/archive/2007/11/26/sql-server-2008-spatial-data-types.aspx
我认为这取决于您最需要做的操作。
如果您需要十进制数的完整值,则使用具有适当精度和比例的十进制。我相信Float超出了你的需求。
如果您经常转换为/来自degomin'sec"分数表示法,我会考虑将每个值存储为整数类型(smallint,tinyint,tinyint,smallint?)。
我会使用具有适当精度的十进制数据。