Biorąc pod uwagę, że będę wykonywać obliczenia dla par lat / long, jaki typ danych najlepiej nadaje się do użycia z bazą danych MySQL?
mysql
database-design
maps
mapping
latitude-longitude
Codebeef
źródło
źródło
Odpowiedzi:
Używaj rozszerzeń przestrzennych MySQL z GIS.
źródło
Google zapewnia początek ukończenia rozwiązania PHP / MySQL dla przykładowej aplikacji „Store Locator” z Google Maps. W tym przykładzie przechowują wartości lat / lng jako „Float” o długości „10,6”
http://code.google.com/apis/maps/articles/phpsqlsearch.html
źródło
FLOAT(10,6)
pozostawia 4 cyfry dla całkowitej liczby współrzędnych. I nie, znak się nie liczy - pochodzi od (nie) podpisanego atrybutu.Double
dla LaravelaZasadniczo zależy to od precyzji potrzebnej do lokalizacji. Używając DOUBLE uzyskasz precyzję 3,5 nm. DECIMAL (8,6) / (9,6) spada do 16 cm. FLOAT ma 1,7 m ...
Ta bardzo interesująca tabela ma bardziej kompletną listę: http://mysql.rjweb.org/doc.php/latlng :
Mam nadzieję że to pomoże.
źródło
Rozszerzenia przestrzenne MySQL są najlepszą opcją, ponieważ masz do dyspozycji pełną listę operatorów przestrzennych i indeksów. Indeks przestrzenny pozwoli bardzo szybko wykonać obliczenia oparte na odległości. Należy pamiętać, że od wersji 6.0 rozszerzenie przestrzenne jest nadal niekompletne. Nie odkładam MySQL Spatial, tylko informuję o pułapkach, zanim dojdziesz do tego zbyt daleko.
Jeśli masz do czynienia wyłącznie z punktami i tylko z funkcją ODLEGŁOŚCI, to jest w porządku. Jeśli konieczne jest wykonanie jakichkolwiek obliczeń za pomocą wielokątów, linii lub punktów buforowanych, operatory przestrzenne nie zapewniają dokładnych wyników, chyba że użyje się operatora „powiązania”. Zobacz ostrzeżenie na górze 21.5.6 . Relacje, takie jak zawiera, wewnątrz lub przecina, wykorzystują MBR, a nie dokładny kształt geometrii (tzn. Elipsa jest traktowana jak prostokąt).
Ponadto odległości w MySQL Spatial są w tych samych jednostkach, co Twoja pierwsza geometria. Oznacza to, że jeśli używasz stopni dziesiętnych, wówczas twoje pomiary odległości są w stopniach dziesiętnych. Utrudni to uzyskanie dokładnych wyników, gdy zdobędziesz jeszcze więcej od równika.
źródło
Kiedy zrobiłem to dla bazy danych nawigacji zbudowanej z ARINC424, przeprowadziłem sporo testów i patrząc wstecz na kod, użyłem DECIMAL (18,12) (Właściwie NUMERYCZNY (18,12), ponieważ był firebird).
Liczba zmiennoprzecinkowa i liczba podwójna nie są tak precyzyjne i mogą powodować błędy zaokrąglania, co może być bardzo złe. Nie pamiętam, czy znalazłem jakieś rzeczywiste dane, które miałyby problemy - ale jestem całkiem pewien, że niemożność dokładnego przechowywania w liczbach zmiennoprzecinkowych lub podwójnych może powodować problemy
Chodzi o to, że używając stopni lub radianów znamy zakres wartości - a część ułamkowa potrzebuje jak najwięcej cyfr.
W MySQL Spatial Rozszerzenia są dobrą alternatywą, ponieważ idą OpenGIS geometrii modelu . Nie korzystałem z nich, ponieważ musiałem mieć przenośną bazę danych.
źródło
a*b
nie było równeb*a
(dla niektórych wartości). Było wiele przykładów nieco jak:2+2 = 3.9999
. Standard wyczyścił wiele bałaganu i został „szybko” przyjęty przez praktycznie każdy sprzęt i oprogramowanie. Tak więc ta dyskusja jest aktualna nie tylko od 2008 roku, ale przez jedną trzecią wieku.Zależy od wymaganej precyzji.
Od: http://mysql.rjweb.org/doc.php/latlng
Podsumować:
DOUBLE
.DECIMAL(8,6)/(9,6)
.Począwszy od MySQL 5.7 , rozważ użycie typów danych przestrzennych (SDT), szczególnie
POINT
do przechowywania pojedynczej współrzędnej. Przed wersją 5.7 SDT nie obsługuje indeksów (z wyjątkiem 5.6, gdy typem tabeli jest MyISAM).Uwaga:
POINT
klasy kolejność argumentów do przechowywania współrzędnych musi być następującaPOINT(latitude, longitude)
.ST_Distance
) i określania, czy jeden punkt jest zawarty w innym obszarze (ST_Contains
).źródło
CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;
ostrzeżenie o ograniczeniach SDT, jak wspomniał James , być może twoja odpowiedź będzie bardziej zwięzła i precyzyjna w pomaganiu również innym ludziom. ..Na podstawie tego artykułu wiki http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy odpowiednim typem danych w MySQL jest liczba dziesiętna (9,6) do przechowywania długości i szerokości geograficznej w osobnych polach.
źródło
Użyj
DECIMAL(8,6)
dla szerokości geograficznej (90 do -90 stopni) iDECIMAL(9,6)
długości geograficznej (180 do -180 stopni). W przypadku większości aplikacji wystarczy 6 miejsc po przecinku. Oba powinny być „podpisane”, aby uwzględnić wartości ujemne.źródło
DECIMAL
typ jest przeznaczony do obliczeń finansowych, w przypadku których niefloor/ceil
są akceptowane. ZwykłyFLOAT
znacznie przewyższaDECIMAL
.Według Google Maps nie trzeba daleko się posuwać, najlepiej FLOAT (10,6) dla lat i lng.
źródło
lat FLOAT( 10, 6 ) NOT NULL,
lng FLOAT( 10, 6 ) NOT NULL
FLOAT
składnia jest przestarzała od dniamysql 8.0.17
. Mysql zaleca teraz używanieFLOAT
bez żadnych parametrów dokładności dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html i dev.mysql.com/doc/refman/5.5/en/floating-point- types.htmlPrzechowujemy szerokość / długość geograficzną X 1 000 000 w naszej bazie danych Oracle jako LICZBY, aby uniknąć błędów zaokrąglania z podwójnymi.
Biorąc pod uwagę, że szerokość / długość geograficzna do 6. miejsca po przecinku wynosiła 10 cm dokładności, to było wszystko, czego potrzebowaliśmy. Wiele innych baz danych również przechowuje długość / szerokość do 6 miejsc po przecinku.
źródło
W zupełnie innej i prostszej perspektywie:
VARCHAR
), np .: „ -0000.0000001, -0000.000000000000001 ” (długość 35, a jeśli liczba ma więcej niż 7 cyfr dziesiętnych, wówczas zostanie zaokrąglona);google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
W ten sposób nie musisz się martwić indeksowaniem liczb i wszystkimi innymi problemami związanymi z typami danych, które mogą popsuć twoje współrzędne.
źródło
w zależności od zastosowania sugeruję użycie FLOAT (9,6)
klucze przestrzenne dadzą ci więcej funkcji, ale w testach wydajności pływaki są znacznie szybsze niż klucze przestrzenne. (0,01 VS 0,001 w systemie AVG)
źródło
MySQL używa double dla wszystkich pływaków ... Więc użyj double. Użycie liczby zmiennoprzecinkowej doprowadzi do nieprzewidywalnych zaokrąglonych wartości w większości sytuacji
źródło
DOUBLE
. MySQL pozwala przechowywać dane jako 4-bajtoweFLOAT
lub 8-bajtoweDOUBLE
. Tak więc istnieje prawdopodobieństwo utraty precyzji podczas przechowywania wyrażenia wFLOAT
kolumnie.Chociaż nie jest to optymalne dla wszystkich operacji, jeśli tworzysz kafelki mapy lub pracujesz z dużą liczbą znaczników (kropek) za pomocą tylko jednej projekcji (np. Mercator, jak Google Maps i wiele innych śliskich ram map), znalazłem to, co Nazywam „Ogromny Układ Współrzędnych”, aby był naprawdę bardzo przydatny. Zasadniczo przechowujesz współrzędne pikselowe xiy przy pewnym zbliżeniu - używam poziomu powiększenia 23. Ma to kilka zalet:
O tym wszystkim mówiłem w niedawnym wpisie na blogu: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/
źródło
Jestem bardzo zaskoczony niektórymi odpowiedziami / komentarzami.
Dlaczego, u licha, ktoś miałby dobrowolnie „wstępnie zmniejszyć” precyzję, a następnie wykonać obliczenia na gorszych liczbach? Brzmi ostatecznie głupio.
Jeśli źródło ma 64-bitową precyzję, na pewno głupio byłoby dobrowolnie naprawić skalę np. 6 miejsc po przecinku i ogranicz precyzję do maksymalnie 9 cyfr znaczących (co dzieje się w przypadku powszechnie proponowanego formatu dziesiętnego 9,6).
Oczywiście dane są przechowywane z precyzją, jaką ma materiał źródłowy. Jedynym powodem zmniejszenia precyzji byłoby ograniczone miejsce do przechowywania.
Dziesiętny format 9,6 powoduje zjawisko przyciągania do siatki. To powinien być ostatni krok, jeśli w ogóle się wydarzy.
Nie zapraszam do mojego gniazda skumulowanych błędów.
źródło
TL; DR
Użyj FLOAT (8,5), jeśli nie pracujesz w NASA / wojsku i nie tworzysz systemów nawigacyjnych samolotów.
Aby w pełni odpowiedzieć na twoje pytanie, musisz rozważyć kilka rzeczy:
Format
Tak więc pierwsza część odpowiedzi brzmi - możesz przechowywać współrzędne w formacie używanym przez twoją aplikację, aby uniknąć ciągłych konwersji tam iz powrotem i uprościć zapytania SQL.
Najprawdopodobniej używasz Map Google lub OSM do wyświetlania danych, a GMaps używają formatu „stopnie dziesiętne 2”. Dzięki temu łatwiej będzie przechowywać współrzędne w tym samym formacie.
Precyzja
Następnie chcesz zdefiniować potrzebną precyzję. Oczywiście możesz przechowywać współrzędne, takie jak „-32.608697550570334,21.278081997935146”, ale czy kiedykolwiek dbałeś o milimetry podczas nawigacji do punktu? Jeśli nie pracujesz w NASA i nie wykonujesz trajektorii satelitów, rakiet lub samolotów, powinieneś być w porządku z dokładnością do kilku metrów.
Powszechnie stosowanym formatem jest 5 cyfr po kropkach, co daje dokładność 50 cm.
Przykład : odległość 1 cm między X 21,278081 8 a X 21,278081 9 . Tak więc 7 cyfr po kropce daje dokładność 1/2 cm, a 5 cyfr po kropce daje precyzję 1/2 metra (ponieważ minimalna odległość między odrębnymi punktami wynosi 1 m, więc błąd zaokrąglenia nie może przekraczać połowy). W większości celów cywilnych powinno wystarczyć.
format minut po przecinku (40 ° 26,767 ′ N 79 ° 58,933 ′ W) daje dokładnie taką samą dokładność jak 5 cyfr po kropce
Energooszczędne miejsce do przechowywania
Jeśli wybrałeś format dziesiętny, twoją współrzędną jest para (-32.60875, 21.27812). Oczywiście wystarczą 2 x (1 bit na znak, 2 cyfry na stopnie i 5 cyfr na wykładnik).
Więc tutaj chciałbym wesprzeć Alix Axel z komentarzy mówiących, że sugestia Google, aby przechowywać go w FLOAT (10,6) jest naprawdę dodatkowa, ponieważ nie potrzebujesz 4 cyfr dla głównej części (ponieważ znak jest oddzielony, a szerokość geograficzna jest ograniczona do 90, a długość geograficzna jest ograniczona do 180). Możesz z łatwością użyć FLOAT (8,5) dla dokładności 1 / 2m lub FLOAT (9,6) dla dokładności 50 / 2cm. Lub możesz nawet przechowywać lat i long w osobnych typach, ponieważ FLOAT (7,5) wystarcza dla lat. Zobacz odwołanie do typów pływaków MySQL . Każdy z nich będzie podobny do normalnego FLOAT i będzie równy 4 bajtom.
Zwykle przestrzeń nie jest obecnie problemem, ale jeśli chcesz naprawdę zoptymalizować pamięć z jakiegoś powodu (Oświadczenie: nie rób wstępnej optymalizacji), możesz skompresować lat (nie więcej niż 91 000 wartości + znak) + długi (nie ponad 181 000 wartości + znak) do 21 bitów, czyli znacznie mniej niż 2xFLOAT (8 bajtów == 64 bitów)
źródło
Funkcje przestrzenne w PostGIS są znacznie bardziej funkcjonalne (tj. Nie są ograniczone do operacji BBOX) niż funkcje przestrzenne MySQL. Sprawdź to: link do tekstu
źródło
Szerokości geograficzne wynoszą od -90 do +90 (stopni), więc DECIMAL (10, 8) jest do tego odpowiedni
długości geograficzne wynoszą od -180 do +180 (stopni), więc potrzebujesz DECIMAL (11, 8).
Uwaga: Pierwsza liczba to całkowita liczba zapisanych cyfr, a druga to liczba po przecinku.
W skrócie:
lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL
źródło
Sugeruję użycie typu danych Float dla SQL Server.
źródło
Długie obliczenia wymagają precyzji, więc używaj pewnego rodzaju typu dziesiętnego i zwiększ dokładność co najmniej 2 razy więcej niż liczba, którą zapiszesz, aby wykonać obliczenia matematyczne. Nie wiem o moich typach danych SQL, ale na serwerze SQL ludzie często używają liczb zmiennoprzecinkowych lub rzeczywistych zamiast dziesiętnych i wpadają w kłopoty, ponieważ są to szacunkowe liczby, a nie liczby rzeczywiste. Upewnij się więc, że używany typ danych jest prawdziwym typem dziesiętnym, a nie zmiennoprzecinkowym, i wszystko powinno być w porządku.
źródło
A
FLOAT
powinno dać ci całą precyzję, jakiej potrzebujesz, i być lepsze dla funkcji porównawczych niż przechowywanie każdej współrzędnej jako łańcucha lub podobnego.Jeśli Twoja wersja MySQL jest wcześniejsza niż 5.0.3, może być konieczne zwrócenie uwagi na niektóre błędy porównania zmiennoprzecinkowego .
źródło
DECIMAL
miał (przed 5.0.3) pewne błędy z powodu zastosowania implementacji swobodnej.