纬度和经度的数据类型是啥?

Posted

技术标签:

【中文标题】纬度和经度的数据类型是啥?【英文标题】:Which data type for latitude and longitude?纬度和经度的数据类型是什么? 【发布时间】:2011-12-30 08:18:05 【问题描述】:

我是 PostgreSQL 和 PostGIS 的新手。我想在 PostgreSQL 9.1.1 数据库表中存储纬度和经度值。我将计算两点之间的距离,使用这个位置值找到更近的点。

我应该为纬度和经度使用哪种数据类型?

【问题讨论】:

如果你在做两点(二维纬度/经度地图),我会使用几何数据类型。如果您需要在距离计算中引入地球的高度或曲率,Geography 就是您想要去的地方。 以下任何答案是否解决了您的问题?如果是这样,我鼓励您选择一个作为答案:) 【参考方案1】:

您可以使用数据类型point - 结合(x,y) 可以是您的纬度/经度。占用 16 个字节:内部有 2 个float8 数字。

或者将其设为float 类型的两列(= float8double precision)。每个 8 个字节。 或者 real (= float4) 如果不需要额外的精度。每个 4 个字节。 如果您需要绝对精度,甚至是numeric。每组 4 位 2 个字节,加上 3 - 8 个字节的开销。

阅读有关numeric types 和geometric types 的精美手册。


geometrygeography 数据类型由附加模块 PostGIS 提供,并占据表中的 one 列。每个点占用 32 个字节。那里有一些额外的开销,比如 SRID。这些类型存储 (long/lat),而不是 (lat/long)。

开始阅读PostGIS manual here。

【讨论】:

我不建议使用 float 数据类型。它使坐标计算变得非常复杂。您应该使用 PostGIS 和 geography 数据类型进行此类计算。 这真的是一本很好的手册,不是吗?文档中的一个光辉榜样。 存储 long、lat 和 geog 会比尝试为原始 long lat 解析 geog 更快吗? @Dan:视情况而定。请提出一个新的问题并提供详细信息。您始终可以链接到此以获取上下文。评论不是新问题的地方。【参考方案2】:

在 PostGIS 中,对于具有纬度和经度的点,存在地理数据类型。

添加列:

alter table your_table add column geog geography;

插入数据:

insert into your_table (geog) values ('SRID=4326;POINT(longitude latitude)');

4326 是空间参考 ID,表示它的数据以经度和纬度为单位,与 GPS 相同。更多信息:http://epsg.io/4326

顺序是经度,纬度 - 所以如果你把它绘制成地图,它是 (x, y)。

要找到最近的点,您首先需要创建空间索引:

create index on your_table using gist (geog);

然后请求距离给定点最近的 5 个:

select * 
from your_table 
order by geog <-> 'SRID=4326;POINT(lon lat)' 
limit 5;

【讨论】:

澄清 SRID 4326 需要按该顺序获得纬度经度。但是 PostGIS 对 SRID 4326 的解释需要按该顺序排列经度纬度。示例对于 PostGIS 使用是正确的。 postgis.net/2013/08/18/tip_lon_lat SELECT * FROM table_name ORDER BY location point '(-74.013, 40.711)' LIMIT 10;这里点第一个元素是经度,第二个元素是纬度【参考方案3】:

我强烈推荐PostGis。它特定于这种数据类型,它具有计算点之间距离的开箱即用的方法,以及您将来会发现有用的其他 GIS 操作

【讨论】:

【参考方案4】:

如果您不需要 PostGIS 提供的所有功能,Postgres(现在)提供了一个名为 earthdistance 的扩展模块。它使用point 或cube 数据类型,具体取决于您对距离计算的准确度需求。

您现在可以使用 earth_box 函数来 - 例如 - 查询某个位置一定距离内的点。

【讨论】:

【参考方案5】:

在 PostGIS 中,几何比地理(圆形地球模型)更受欢迎,因为计算更简单,因此速度更快。它还具有更多可用功能,但在很长的距离上不太准确。

将您的 CSV 长和纬度字段导入到 DECIMAL(10,6) 列。 6 位是 10 厘米精度,对于大多数用例来说应该足够了。然后将您导入的数据转换为正确的 SRID

走错路了!

/* try what seems the obvious solution */
DROP TABLE IF EXISTS public.test_geom_bad;
-- Big Ben, London
SELECT ST_SetSRID(ST_MakePoint(-0.116773, 51.510357),4326) AS geom
INTO public.test_geom_bad;

正确的方法

/* add the necessary CAST to make it work */
DROP TABLE IF EXISTS public.test_geom_correct;
SELECT ST_SetSRID(ST_MakePoint(-0.116773, 51.510357),4326)::geometry(Geometry, 4326) AS geom
INTO public.test_geom_correct;

验证 SRID 不为零!

/* now observe the incorrect SRID 0 */
SELECT * FROM public.geometry_columns
WHERE f_table_name IN ('test_geom_bad','test_geom_correct');

使用 WKT 查看器验证 long lat 参数的顺序并

SELECT ST_AsEWKT(geom) FROM public.test_geom_correct

然后索引它以获得最佳性能

CREATE INDEX idx_target_table_geom_gist
    ON target_table USING gist(geom);

【讨论】:

“在很长的距离上不太准确。”你能提一下你所说的“长距离”是什么意思吗?我在很多博客上都读过这篇文章,但没有一个被认为是远距离的实际范围,我很难弄清楚该使用哪个。 @GCQ 我建议这里的最佳方法是让您获取一些地理数据样本,然后使用 Geometry 一次测量距离,然后使用 Geography 并比较结果。这是因为坐标参考系统(投影)的精度因地域而异。 select st_point(12.0, 42.0)::geometry(Geometry, 4326) 给出错误:几何 SRID (0) 与列 SRID (4326) 不匹配,但 select ST_SetSRID(ST_Point(12.0, 42.0),4326) 有效¯_(ツ)_/¯ @mathieu 感谢您指出这一点。我已更正并改进了答案,以更好地突出错误设置 SRID 的风险。【参考方案6】:

使用Point数据类型将经度和纬度存储在单列中:

CREATE TABLE table_name (
    id integer NOT NULL,
    name text NOT NULL,
    location point NOT NULL,
    created_on timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT table_name_pkey PRIMARY KEY (id)
)

在“位置”列上创建索引:

CREATE INDEX ON table_name USING GIST(location);

GiST 索引能够优化“最近邻”搜索:

SELECT * FROM table_name ORDER BY location <-> point '(-74.013, 40.711)' LIMIT 10;

注意:点第一个元素是经度,第二个元素是纬度。

更多信息请查看Query Operators。

【讨论】:

以上是关于纬度和经度的数据类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

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

用于存储纬度和经度的数据类型 [重复]

float 和 double 数据类型是不是适合存储纬度和经度? [复制]

存储经度和纬度值需要哪种数据类型[重复]

如何将 csv 中的纬度和经度数据导入 MySQL 中的点数据类型列

在 Mysql 中存储经度/纬度的数据类型