Jaki typ danych dla szerokości i długości geograficznej?

154

Jestem nowicjuszem w PostgreSQL i PostGIS. Chcę przechowywać wartości szerokości i długości geograficznej w tabeli bazy danych PostgreSQL 9.1.1. Obliczę odległość między dwoma punktami, znajdę bliższe punkty, używając tych wartości lokalizacji.

Jakiego typu danych należy użyć w przypadku szerokości i długości geograficznej?

user1008404
źródło
4
Jeśli robisz dwa punkty (mapa 2D szerokości / długości geograficznej) użyłbym typu danych Geometry. Jeśli chcesz wprowadzić wysokość lub krzywiznę ziemi w obliczeniach odległości, Geografia jest miejscem, do którego chcesz się udać.
Dwunasty
4
Czy którakolwiek z poniższych odpowiedzi dotyczyła Twojego pytania? Jeśli tak, to zachęcam do wybrania jednego jako odpowiedzi :)
Volte

Odpowiedzi:

140

Możesz użyć typu danych point- kombinacje, (x,y)które mogą być twoją szerokością / długością. Zajmuje 16 bajtów: 2 float8liczby wewnętrznie.

Lub utwórz dwie kolumny typu float(= float8lub double precision). 8 bajtów każdy.
Lub real(= float4), jeśli dodatkowa precyzja nie jest potrzebna. 4 bajty każdy.
Lub nawet numericjeśli potrzebujesz absolutnej precyzji. 2 bajty na każdą grupę 4 cyfr plus 3 - 8 bajtów narzut.

Przeczytaj dokładną instrukcję dotyczącą typów numerycznych i geometrycznych .


Te geometryi geographytypy danych są dostarczane przez dodatkowy moduł PostGIS i zajmują jedną kolumnę w tabeli. Każdy zajmuje 32 bajty na punkt. Jest tam dodatkowe obciążenie, takie jak SRID. Te typy przechowują (długie / szer.), A nie (szer./dług.).

Zacznij czytać instrukcję PostGIS tutaj .

Erwin Brandstetter
źródło
5
Nie polecam używania floattypu danych. To sprawia, że ​​obliczenia ze współrzędnymi są bardzo skomplikowane. Do geographytakich obliczeń należy używać PostGIS i typu danych.
13
9
To naprawdę dobra instrukcja, prawda? Świetny przykład w dokumentacji.
otocan
1
Czy przechowywanie long, lat i geog byłoby szybsze niż próbowanie parse geog dla oryginalnego long lat?
Dan
1
@Dan: Zależy. Proszę zadać nowe pytanie ze szczegółami. Zawsze możesz utworzyć link do tego, aby uzyskać kontekst. Komentarze nie są miejscem na nowe pytania.
Erwin Brandstetter
40

W PostGIS dla punktów o szerokości i długości geograficznej istnieje typ danych geograficznych.

Aby dodać kolumnę:

alter table your_table add column geog geography;

Aby wstawić dane:

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

4326 to przestrzenny identyfikator odniesienia, który podaje dane w stopniach długości i szerokości geograficznej, tak samo jak w GPS. Więcej na ten temat: http://epsg.io/4326

Kolejność to długość i szerokość geograficzna - więc jeśli narysujesz to jako mapę, to (x, y).

Aby znaleźć najbliższy punkt, musisz najpierw utworzyć indeks przestrzenny:

create index on your_table using gist (geog);

a następnie poproś, powiedzmy, o 5 najbliżej danego punktu:

select * 
from your_table 
order by geog <-> 'SRID=4326;POINT(lon lat)' 
limit 5;
Darafei Praliaskouski
źródło
1
Wyjaśnienie, że SRID 4326 wymaga szerokości geograficznej w tej kolejności. Ale interpretacja SRID 4326 przez PostGIS wymaga szerokości geograficznej w tej kolejności. Przykład jest poprawny do użytku PostGIS. postgis.net/2013/08/18/tip_lon_lat
hahmed
26

Zdecydowanie opowiadam się za PostGis . Jest specyficzny dla tego rodzaju danych i ma nieszablonowe metody obliczania odległości między punktami, wśród innych operacji GIS, które mogą być przydatne w przyszłości

tvieira
źródło
5

Jeśli nie potrzebujesz wszystkich funkcji oferowanych przez PostGIS, Postgres (obecnie) oferuje moduł rozszerzający o nazwie Earthdistance . Wykorzystuje typ danych punktowych lub sześciennych w zależności od potrzeb dokładności w obliczeniach odległości.

Możesz teraz użyć funkcji earth_box, aby na przykład zapytać o punkty w określonej odległości od lokalizacji.

Hans Bouwmeester
źródło
2

W PostGIS Geometria jest preferowana w stosunku do Geografii (model okrągłej ziemi), ponieważ obliczenia są znacznie prostsze, a zatem szybsze. Posiada również WIELE więcej dostępnych funkcji, ale jest mniej dokładny na bardzo dużych odległościach.

Zaimportuj plik CSV do długich pól do DECIMAL(10,6)kolumn. 6 cyfr to dokładność 10 cm, w większości przypadków powinno wystarczyć.

Następnie prześlij zaimportowane dane

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;

Sprawdź, czy SRID nie wynosi zero!

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

Sprawdź kolejność parametru długiej szerokości geograficznej za pomocą przeglądarki WKT i ST_AsEWKT(target_table.geom).

Następnie zindeksuj go, aby uzyskać najlepszą wydajność

CREATE INDEX idx_target_table_geom_gist
    ON target_table USING gist(geom);
golfalot
źródło