Какой тип данных для широты и долготы?


154

Я новичок в PostgreSQL и PostGIS. Я хочу хранить значения широты и долготы в таблице базы данных PostgreSQL 9.1.1. Я вычислю расстояние между двумя точками, найду более близкие точки, используя значения этого местоположения.

Какой тип данных я должен использовать для широты и долготы?


4
Если вы делаете две точки (2D широта / долгота), я бы использовал тип данных Geometry. Если вам нужно ввести высоту или кривизну Земли в ваших дистанционных расчетах, вам нужна география.
Двенадцатое

4
Был ли какой-либо из ответов ниже на ваш вопрос? Если это так, я призываю вас выбрать один из них в качестве ответа :)
Volte

Ответы:


140

Вы можете использовать тип данных point- объединяет, (x,y)который может быть вашим широтой / долготой. Занимает 16 байтов: 2 float8числа внутри.

Или сделайте это двумя столбцами типа float(= float8или double precision). 8 байтов каждый.
Или real(= float4), если дополнительная точность не требуется. 4 байта каждый.
Или даже numericесли вам нужна абсолютная точность. 2 байта для каждой группы из 4 цифр, плюс 3 - 8 байтов.

Прочитайте прекрасное руководство о числовых типах и геометрических типах .


Эти geometryи geographyтипы данных обеспечиваются дополнительным модулем PostGIS и занимают один столбец в таблице. Каждый занимает 32 байта за точку. Там есть некоторые дополнительные издержки, такие как SRID. Эти типы хранят (long / lat), а не (lat / long).

Начните читать руководство PostGIS здесь .


5
Я бы не рекомендовал использовать floatтип данных. Это делает расчет с координатами очень сложным. Вы должны использовать PostGIS и geographyтип данных для таких расчетов.
m13r

9
Это действительно хорошее руководство, не так ли? Яркий пример в документации.
otocan

1
Будет ли быстрее хранить long, lat и geog, пытаясь разобрать geog для оригинального long lat?
Дан

1
@ Дан: Зависит. Пожалуйста, задайте новый вопрос с деталями. Вы всегда можете связаться с этим для контекста. Комментарии не место для новых вопросов.
Эрвин Брандстеттер

40

В PostGIS для точек с широтой и долготой существует тип данных географии.

Чтобы добавить столбец:

alter table your_table add column geog geography;

Чтобы вставить данные:

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

4326 - это идентификатор пространственной привязки, который говорит, что данные в градусах долготы и широты, такие же, как в 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;

1
Пояснение: SRID 4326 хочет широту и долготу в этом порядке. Но для интерпретации SRID 4326 PostGIS требуется широта в этом порядке. Пример подходит для использования PostGIS. postgis.net/2013/08/18/tip_lon_lat
Хахмед

26

Я настоятельно рекомендую PostGis . Он специфичен для этого типа данных и имеет готовые методы для расчета расстояния между точками, среди других операций ГИС, которые вы можете найти полезными в будущем


5

Если вам не нужны все функции, которые предлагает PostGIS, Postgres (в настоящее время) предлагает модуль расширения, называемый earthdistance . Он использует тип данных точки или куба в зависимости от вашей точности, необходимой для расчета расстояния.

Теперь вы можете использовать функцию earth_box, например, для запроса точек на определенном расстоянии от местоположения.


2

В PostGIS геометрия предпочтительнее, чем география (модель с круглой землей), потому что вычисления намного проще, а значит, быстрее. Он также имеет МНОГИЕ более доступные функции, но менее точен на очень больших расстояниях.

Импортируйте CSV в длинные поля lat в DECIMAL(10,6)столбцы. 6 цифр с точностью до 10 см, должно быть достаточно для большинства случаев использования.

Затем приведите ваши импортированные данные

SELECT 
    --ST_SetSRID(ST_Point(long, lat),4326) geom -- the wrong way because SRID not set in geometry_columns table
    ST_Point(long, lat)::geometry(Geometry, 4326) geom
INTO target_table
FROM source_table;

Убедитесь, что SRID не равен нулю!

SELECT * FROM public.geometry_columns WHERE f_table_name = 'target_table';

Проверьте порядок вашего параметра long lat с помощью средства просмотра WKT и ST_AsEWKT(target_table.geom).

Затем индексируйте его для лучшей производительности

CREATE INDEX idx_target_table_geom_gist
    ON target_table USING gist(geom);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.