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


154

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

Який тип даних я повинен використовувати для широти та довготи?


4
Якщо ви робите два пункти (двовимірна карта / лон-карта), я б використовував тип даних геометрії. Якщо вам потрібно ввести висоту або кривизну землі у ваших відстанях, то ви хочете піти Географія.
Дванадцяте

4
Чи відповів якийсь із наведених нижче відповідей на ваше запитання? Якщо так, то рекомендую вибрати як відповідь :)
Volte

Відповіді:


140

Ви можете використовувати тип даних point- комбайн, (x,y)який може бути вашим lat / long. Займає 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тип даних. Це робить обчислення з координатами дуже складним. geographyДля таких розрахунків слід використовувати PostGIS і тип даних.
m13r

9
Це дійсно чудовий посібник, чи не так? Яскравий приклад в документації.
otocan

1
Чи було б швидше зберігати long, lat та geog, намагаючись проаналізувати geog для початкового довгого lat?
Дан

1
@Dan: Залежить. Будь ласка, задайте нове запитання з деталями. Ви завжди можете зв’язатись із цим для контексту. Коментарі - це не місце для нових питань.
Ервін Брандстеттер

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
hahmed

26

Я рішуче виступаю за PostGis . Це специфічно для такого типу даних, і він має нестандартні методи для обчислення відстані між точками, серед інших операцій ГІС, які ви можете знайти корисними в майбутньому


5

Якщо вам не потрібна вся функція, що пропонує PostGIS, Postgres (нині) пропонує модуль розширення, який називається earthdistance . Він використовує тип даних точки або куба залежно від вашої потреби в точності для обчислення відстані.

Тепер ви можете використовувати функцію Earth_box для -для прикладу запиту на точки, що знаходяться на певній відстані від місця.


2

У PostGIS геометрія віддається перевазі географії (круглоземна модель), оскільки обчислення набагато простіші, тому швидші. Він також має багато доступних функцій, але менш точний на дуже великих відстанях.

Імпортуйте свій CSV у довгі лати поля до 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';

Перевірте порядок довгого параметра 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.