Was ist der ideale Datentyp zum Speichern von Längen- und Breitengraden in einer MySQL-Datenbank?

430

In Anbetracht dessen, dass ich Berechnungen für Lat / Long-Paare durchführen werde, welcher Datentyp eignet sich am besten für die Verwendung mit einer MySQL-Datenbank?

Codebeef
quelle
1
Ich fand diesen Link sehr nützlich: howto-use-mysql-spatial-ext.blogspot.com/2007/11/… Er ist vielleicht etwas älter, enthält aber eine vollständige Erklärung mit Beispielen.
Madc
Imho verstehen die meisten Leute hier nicht, was passiert. Sobald der App-Code eine Zahl berührt , wird die Zahl höchstens doppelt genau , vorausgesetzt, man verwendet Doppel (was die meisten tun) . Es dann mit nur einer Million Dezimalstellen zu speichern, bringt nichts. Das Speichern mit einer begrenzten Anzahl von Dezimalstellen (z. B. 6) zerstört einen Teil dieser Genauigkeit und fügt bei jedem erneuten Schreiben in die Datenbank einen akkumulierten Fehler hinzu . Ein Doppel trägt ca. 16 signifikante Zahlen, möglicherweise alle Dezimalstellen. Das Abschaben von 10 von ihnen erzeugt im Laufe der Zeit einen akkumulierten Fehler. Es ist aus gutem Grund "Gleitkomma". Fortsetzung
Sturmwind
Fortsetzung: 6 Dezimalstellen können in Ordnung sein, wenn eine Figur, wie sie von einer externen Quelle stammt, unverändert und zum ersten Mal gespeichert wird - als Ausgangsmaterial. Wenn Sie eine Berechnung jedoch nur einmal durchführen und erneut speichern, ist es dumm , einen Teil der Genauigkeit durch Erzwingen eines bestimmten Dezimalformats zu entfernen. Das Ausführen der Berechnung ausschließlich innerhalb des Servers kann unterschiedlich sein (der Server verwendet möglicherweise intern etwas anderes als das Doppelte oder nicht), und die Verwendung schlechterer numerischer Darstellungen als das Doppelte in der App-Berechnung von c verringert die Notwendigkeit einer Speichergenauigkeit gleichermaßen.
Sturmwind
Fortsetzung: WENN der Server die Nummer trotz der behaupteten "9.6" (von der ich nicht weiß, ob dies der Fall ist) mit höherer Genauigkeit speichert , ist nichts davon von Bedeutung, und das Format ist nur eine Frage der Bequemlichkeit - hat wenig zu tun mit Präzisionsproblemen tun. Aber ich wäre nicht überrascht, wenn der Server tatsächlich eine Zahl mit diesem Format auf 6 Dezimalstellen runden würde.
Sturmwind
Cont: Schließlich: Für lat, lon's ist die 6. Dezimalstelle eine Frage des Einrastens in eine ca. 11-Zentimeter-Gitter. Jedes Mal, wenn man mit 6 Dezimalstellen liest (berührt), berechnet und erneut speichert, kommt es zu einem neuen Einrasten (= akkumulierter Fehler). Wenn alle Fehler in die gleiche Richtung gehen, liegt ein großer Fehler vor. Wenn temporäre Multiplikationen durchgeführt werden (z. B. Vergrößern, Subtrahieren und Verkleinern), kann es sogar noch größer werden. Schaben Sie keine Präzision ohne einen guten Rason!
Sturmwind

Antworten:

160

Verwenden Sie die räumlichen Erweiterungen von MySQL mit GIS.

Kirk Strauser
quelle
24
Haben Sie weitere Links zu Beispielen oder andere Informationen darüber, wie Sie am besten damit beginnen können?
Codebeef
6
MYSQL Spatial ist eine gute Option, weist jedoch immer noch erhebliche Einschränkungen und Einschränkungen auf (Stand 6). Bitte sehen Sie meine Antwort unten ...
James Schek
1
@ James Schek ist richtig. Außerdem führt MySQL alle Berechnungen mit euklidischer Geometrie durch, sodass es keinen realen Anwendungsfall für lat / lng darstellt.
mkuech
FYI; MySQL unterstützt den räumlichen Index nur mit * .myisam-Tabellen, dh der ISAM-Engine. Link: dev.mysql.com/doc/refman/5.0/en/creating-spatial-indexes.html
PodTech.io
Schauen Sie sich diesen Artikel am Ende des Update-Teils an: mysqlserverteam.com/mysql-5-7-and-gis-an-example
Jaspal Singh
148

Google bietet eine Start-zu-Ende-PHP / MySQL-Lösung für eine Beispielanwendung "Store Locator" mit Google Maps. In diesem Beispiel speichern sie die lat / lng-Werte als "Float" mit einer Länge von "10,6".

http://code.google.com/apis/maps/articles/phpsqlsearch.html

Ted Avery
quelle
11
Google versteht eindeutig nicht, wie die FLOAT-Spezifikation funktioniert: Es bleiben FLOAT(10,6)4 Ziffern für den ganzzahligen Teil der Koordinate. Und nein, das Zeichen zählt nicht - das kommt vom (nicht) signierten Attribut.
Alix Axel
2
Aber wenn Sie als integraler Teil Werte von [0, 180] speichern müssen, sollten diese mehr als genug sein, oder?
Hrvoje Golcic
37
@AlixAxel Ich denke, Google weiß, was es tut. Denn es heißt: " . Mit den aktuellen Zoom - Funktionen von Google Maps, nur 6 Stellen genau hinter dem Komma benötigen sollte Das wird die Felder speichern 6 Stellen nach dem Komma, läßt plus bis zu 4 Stellen vor dem Komma, zB - 123,456789 Grad. ". Wenn unsigned aktiviert ist, lautet das Muster 1234.567890 . Also keine Probleme.
1,44 MB
16
@AlixAxel Er zählt die Zahlen in der Sequenz ab; keine tatsächliche Koordinate verwenden ...
Andrew Ellis
8
Verwenden des Datentyps Doublefür Laravel
FooBar
133

Grundsätzlich hängt es von der Präzision ab, die Sie für Ihre Standorte benötigen. Mit DOUBLE haben Sie eine Genauigkeit von 3,5 nm. DECIMAL (8,6) / (9,6) geht auf 16 cm zurück. FLOAT ist 1,7m ...

Diese sehr interessante Tabelle enthält eine vollständigere Liste: http://mysql.rjweb.org/doc.php/latlng :

Datatype               Bytes            Resolution

Deg*100 (SMALLINT)     4      1570 m    1.0 mi  Cities
DECIMAL(4,2)/(5,2)     5      1570 m    1.0 mi  Cities
SMALLINT scaled        4       682 m    0.4 mi  Cities
Deg*10000 (MEDIUMINT)  6        16 m     52 ft  Houses/Businesses
DECIMAL(6,4)/(7,4)     7        16 m     52 ft  Houses/Businesses
MEDIUMINT scaled       6       2.7 m    8.8 ft
FLOAT                  8       1.7 m    5.6 ft
DECIMAL(8,6)/(9,6)     9        16cm    1/2 ft  Friends in a mall
Deg*10000000 (INT)     8        16mm    5/8 in  Marbles
DOUBLE                16       3.5nm     ...    Fleas on a dog

Hoffe das hilft.

Simon
quelle
2
Ich muss einen konstruktiven, detaillierten Kommentar schreiben, der sich auf den Inhalt der Beiträge konzentriert, daher werde ich sagen, dass ich bei der Beobachtung der Genauigkeitstabelle auf der Website von Rick James leicht amüsiert war über die Auflösungsbeschreibung "Flöhe auf einem Hund" und Ich fand es ein großes Lob wert. Technisch gesehen war dies eine hilfreiche Darstellung, die mir bei der Entscheidung half, welcher Datentyp beim Speichern von Koordinaten zum Messen des Abstands zwischen zwei Adressen verwendet werden soll. @Simon, ich möchte Ihnen für das Teilen danken.
Sam_Butler
FWIW, die Verwendung von "SMALLINT skaliert" durch diesen Link ist fürchterlich ineffizient. Oguzhans Antwort ist eine großartige Möglichkeit, Long / Lat mit 7 Nachkommastellen in einem 4-Byte-Int mit Vorzeichen zu speichern . Große Präzision (~ 1 cm) bei kleiner Größe (4B).
ToolmakerSteve
74

Die räumlichen Erweiterungen von MySQL sind die beste Option, da Ihnen die vollständige Liste der räumlichen Operatoren und Indizes zur Verfügung steht. Mit einem räumlichen Index können Sie sehr schnell entfernungsbasierte Berechnungen durchführen. Bitte beachten Sie, dass ab 6.0 die Spatial Extension noch unvollständig ist. Ich lege MySQL Spatial nicht ab, sondern informiere Sie nur über die Fallstricke, bevor Sie zu weit kommen.

Wenn Sie sich ausschließlich mit Punkten und nur mit der Funktion DISTANCE befassen, ist dies in Ordnung. Wenn Sie Berechnungen mit Polygonen, Linien oder gepufferten Punkten durchführen müssen, liefern die räumlichen Operatoren keine genauen Ergebnisse, es sei denn, Sie verwenden den Operator "beziehen". Siehe die Warnung oben in 21.5.6 . Beziehungen wie enthalten, innerhalb oder Schnittpunkte verwenden den MBR, nicht die exakte Geometrieform (dh eine Ellipse wird wie ein Rechteck behandelt).

Außerdem sind die Abstände in MySQL Spatial in den gleichen Einheiten wie bei Ihrer ersten Geometrie. Dies bedeutet, wenn Sie Dezimalgrade verwenden, werden Ihre Entfernungsmessungen in Dezimalgraden angegeben. Dies macht es sehr schwierig, genaue Ergebnisse zu erhalten, wenn Sie weiter vom Äquator entfernt sind.

James Schek
quelle
26
Wiederholung: MySQL Spatial Extensions eignen sich nicht zur Berechnung von Großkreisabständen zwischen Punkten auf der Erdoberfläche, dargestellt durch Lat / Long. Ihre Abstandsfunktionen usw. sind nur für kartesische, planare Koordinaten nützlich.
O. Jones
71

Als ich dies für eine Navigationsdatenbank aus ARINC424 tat, habe ich eine ganze Reihe von Tests durchgeführt und im Rückblick auf den Code ein DECIMAL (18,12) (eigentlich ein NUMERIC (18,12) verwendet, weil es ein Feuervogel war).

Floats und Doubles sind nicht so präzise und können zu Rundungsfehlern führen, die sehr schlecht sein können. Ich kann mich nicht erinnern, ob ich echte Daten gefunden habe, bei denen Probleme aufgetreten sind - aber ich bin mir ziemlich sicher, dass die Unfähigkeit, genau in einem Float oder Double zu speichern, Probleme verursachen kann

Der Punkt ist, dass wir bei der Verwendung von Grad oder Bogenmaß den Bereich der Werte kennen - und der Bruchteil die meisten Ziffern benötigt.

Die MySQL Spatial Extensions sind eine gute Alternative, da sie dem OpenGIS-Geometriemodell folgen . Ich habe sie nicht verwendet, weil ich meine Datenbank portabel halten musste.

Richard Harrison
quelle
3
Danke, das war hilfreich. Es fühlt sich komisch an, all diese Fragen und Antworten aus dem Jahr 2008 zu lesen und zu erkennen, dass es bereits vor 8 Jahren war.
Aexl
1
@TheSexiestManinJamaica - Vor IEEE 754-1985 war Computer-Gleitkomma-Hardware chaotisch. Es gab sogar auf Maschinen, wo a*bnicht gleich war b*a(für einige Werte). Es gab viele Beispiele wie : 2+2 = 3.9999. Der Standard räumte viel Chaos auf und wurde von praktisch jeder Hardware und Software „schnell“ übernommen. Diese Diskussion ist also nicht nur seit 2008 gültig, sondern seit einem Drittel eines Jahrhunderts.
Rick James
42

Hängt von der Präzision ab, die Sie benötigen.

Datatype           Bytes       resolution
------------------ -----  --------------------------------
Deg*100 (SMALLINT)     4  1570 m    1.0 mi  Cities
DECIMAL(4,2)/(5,2)     5  1570 m    1.0 mi  Cities
SMALLINT scaled        4   682 m    0.4 mi  Cities
Deg*10000 (MEDIUMINT)  6    16 m     52 ft  Houses/Businesses
DECIMAL(6,4)/(7,4)     7    16 m     52 ft  Houses/Businesses
MEDIUMINT scaled       6   2.7 m    8.8 ft
FLOAT                  8   1.7 m    5.6 ft
DECIMAL(8,6)/(9,6)     9    16cm    1/2 ft  Friends in a mall
Deg*10000000 (INT)     8    16mm    5/8 in  Marbles
DOUBLE                16   3.5nm     ...    Fleas on a dog

Von: http://mysql.rjweb.org/doc.php/latlng

Zusammenfassen:

  • Die genaueste verfügbare Option ist DOUBLE.
  • Der am häufigsten verwendete Typ ist DECIMAL(8,6)/(9,6).

Ab MySQL 5.7 sollten Sie die Verwendung von Spatial Data Types (SDT) in Betracht ziehen , insbesondere POINTzum Speichern einer einzelnen Koordinate. Vor 5.7 unterstützt SDT keine Indizes (mit Ausnahme von 5.6, wenn der Tabellentyp MyISAM ist).

Hinweis:

  • Bei Verwendung von POINTclass muss die Reihenfolge der Argumente zum Speichern von Koordinaten lauten POINT(latitude, longitude).
  • Es gibt eine spezielle Syntax zum Erstellen eines räumlichen Index .
  • Der größte Vorteil der Verwendung von SDT besteht darin, dass Sie Zugriff auf räumliche Analysefunktionen haben , z. B. die Berechnung des Abstands zwischen zwei Punkten ( ST_Distance) und die Bestimmung, ob ein Punkt in einem anderen Bereich enthalten ist ( ST_Contains).
Gajus
quelle
2
Sie kopieren einen eingefügten Teil einer vorherigen Antwort und "fassen" mit etwas zusammen, das der Typ, der diese Tabelle erstellt hat, nicht empfohlen hat : «Wie teile ich? Nun, MySQL ist sehr wählerisch. FLOAT / DOUBLE sind also raus. DECIMAL ist raus. Also stecken wir mit etwas Kludge fest. Im Wesentlichen müssen wir Lat / Lng in eine INT-Größe konvertieren und PARTITION BY RANGE verwenden. » UND «FLOAT hat 24 signifikante Bits; DOUBLE hat 53. (Sie funktionieren nicht mit PARTITIONING, sind jedoch der Vollständigkeit halber enthalten. Oft wird DOUBLE verwendet, ohne zu bemerken, wie viel Overkill es ist und wie viel Platz es benötigt.) »Lassen Sie einfach den SDT-Teil, den Sie geschrieben haben.
Armfoot
1
@Armfoot Wenn Sie sich den Zeitpunkt der Änderungen ansehen, ist es die andere Antwort, die von mir kopiert wurde. Nicht, dass es wichtig wäre: Ich sehe Stack Overflow eher als "Notizen für die Zukunft".
Gajus
1
Nein, er hat nicht von Ihnen kopiert, er hat nur die Tabelle eingefügt, wie Sie es von dem Link getan haben, auf den er 2014 verwiesen hat (Ihr Beitrag stammt aus dem Jahr 2015). Übrigens, ich denke, Sie haben "Special" falsch geschrieben, als Sie Spatial Data Types verknüpft haben . Dieser Teil, den Sie geschrieben haben, ist tatsächlich nützlich für Leute, die anfangen möchten, sie zu verwenden. Wenn Sie weitere Beispiele wie CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;und die Warnung vor SDT-Einschränkungen hinzufügen , wie James erwähnte , wird Ihre Antwort möglicherweise präziser und präziser sein, um auch anderen Menschen zu helfen. ..
Armfoot
@ Gajus - Ich fühle mich geehrt, dass zwei von Ihnen mein Dokument gefunden haben! (Nein, ich weiß nicht, wie groß ein Floh ist, aber ich hatte das Gefühl, dass es jemandes Aufmerksamkeit erregen würde.)
Rick James
Bei Verwendung der POINT-Klasse muss die Reihenfolge der Argumente zum Speichern von Koordinaten POINT (Längengrad / X, Breitengrad / Y) sein.
AndreyP
19

Verwenden Sie DECIMAL(8,6)für Breitengrad (90 bis -90 Grad) und DECIMAL(9,6)für Längengrad (180 bis -180 Grad). 6 Dezimalstellen sind für die meisten Anwendungen ausreichend. Beide sollten "signiert" sein, um negative Werte zu berücksichtigen.

Alex Holsgrove
quelle
DECIMALTyp ist für Finanzberechnungen vorgesehen, bei denen keine floor/ceilakzeptiert wird. Plain FLOATübertrifft deutlich DECIMAL.
Kondybas
1
@Kondybas - Da die Hauptkosten in einer Datenbank das Abrufen von Zeilen sind, sollte der Leistungsunterschied zwischen Float und Dezimalzahl kein Problem darstellen.
Rick James
14

Laut Google Maps müssen Sie nicht weit gehen. Das Beste ist FLOAT (10,6) für lat und lng.

Mariano Peinador
quelle
Woher hast du diese Informationen? Ich kann sie nicht finden. Nur für den Fall, dass sich etwas ändert.
Webfacer
1
@webfacer, es ist im Abschnitt "Erstellen einer Tabelle in MySQL" hier: developer.google.com/maps/documentation/javascript/… zB lat FLOAT( 10, 6 ) NOT NULL, lng FLOAT( 10, 6 ) NOT NULL
turrican_34
1
@webfacer, Es sieht so aus, FLOATals ob die Syntax ab veraltet ist mysql 8.0.17. MySQL empfiehlt jetzt, nur FLOATohne Präzisionsparameter dev.mysql.com/doc/refman/8.0/de/numeric-type-overview.html und dev.mysql.com/doc/refman/5.5/en/floating-point- zu verwenden. types.html
turrican_34
7

Wir speichern Breiten- / Längengrade X 1.000.000 in unserer Orakel-Datenbank als ZAHLEN, um Rundungsfehler mit Doppelwerten zu vermeiden.

Angesichts der Tatsache, dass der Breiten- / Längengrad bis zur 6. Dezimalstelle 10 cm genau war, war dies alles, was wir brauchten. Viele andere Datenbanken speichern Lat / Long ebenfalls bis zur 6. Dezimalstelle.


quelle
2
Das Multiplizieren mit einer großen Zahl (wie einer Million) ist großartig, wenn Sie viele Daten haben, da ganzzahlige Operationen (z. B. indizierter Abruf) viel schneller sind als Floats.
Kaitlin Duck Sherwood
@KaitlinDuckSherwood - Bits sind Bits - Mir ist kein Grund bekannt, warum ein 32-Bit-Float langsamer abgerufen werden kann (indiziert oder auf andere Weise) als eine 32-Bit-Ganzzahl. Selbst schwebende Mathematik ist heutzutage schnell genug, um kein Problem zu sein. Trotzdem stimme ich dem Kommentar zu, einen impliziten Multiplikator mit einer ganzen Zahl zu verwenden: Er maximiert die Genauigkeit, die Sie aus 32 Bit erhalten. Ein bisschen zukunftssicher, wenn sich die Technologie verbessert.
ToolmakerSteve
6

In einer ganz anderen und einfacheren Perspektive:

  • Wenn Sie sich bei der Anzeige Ihrer Karten, Markierungen, Polygone usw. auf Google verlassen, lassen Sie die Berechnungen von Google durchführen!
  • Sie sparen Ressourcen auf Ihrem Server und speichern Breiten- und Längengrade einfach zusammen als eine einzige Zeichenfolge ( VARCHAR), z. B.: " -0000.0000001, -0000.0000000000001 " (35 Länge und wenn eine Zahl mehr als 7 Dezimalstellen hat, wird sie gerundet);
  • Wenn Google mehr als 7 Dezimalstellen pro Zahl zurückgibt, können Sie diese Daten trotzdem in Ihrer Zeichenfolge speichern, nur für den Fall, dass Sie in Zukunft einige Fluchten oder Mikroben erkennen möchten .
  • Sie können ihre Abstandsmatrix oder ihre Geometriebibliothek verwenden, um Entfernungen zu berechnen oder Punkte in bestimmten Bereichen mit so einfachen Aufrufen zu erkennen:google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • Es gibt viele "serverseitige" APIs, die Sie verwenden können (in Python , Ruby on Rails , PHP , CodeIgniter , Laravel , Yii , Zend Framework usw.) und die Google Maps-API verwenden.

Auf diese Weise müssen Sie sich keine Gedanken über die Indizierung von Zahlen und all die anderen Probleme machen, die mit Datentypen verbunden sind, die Ihre Koordinaten verfälschen können.

Armfuß
quelle
Nicht gut. OP sagte, er würde Berechnungen für die Lat / Lng-Paare durchführen - Ihre Antworten schließen das aus
Yarin
4
@Yarin Dies ist eine beliebte Frage, bei der einige (oder viele) Personen nur eine Antwort darauf benötigen, wie die Koordinaten gemäß ihren eigenen Anforderungen gespeichert werden sollen (viele von ihnen verwenden möglicherweise nur Google Maps). Ihre Ablehnung deutet darauf hin, dass diese Antwort ihnen möglicherweise nicht hilft ... Durch Speichern der Koordinaten in einer Zeichenfolge kennen sie genau die ursprünglichen Werte, die ihnen bereitgestellt wurden (z. B. von Google), was ihnen später helfen wird, wenn sie sich entscheiden, ihre weiterzuentwickeln eigene App und Berechnungen durchführen. Zu diesem Zeitpunkt haben sie immer noch die ursprünglichen Rohdaten, nur weil sie es nicht mit Conversions vermasselt haben.
Armfuß
4

Abhängig von Ihrer Anwendung empfehle ich die Verwendung von FLOAT (9,6).

Mit räumlichen Schlüsseln erhalten Sie mehr Funktionen, aber bei Produktionsbenchmarks sind die Floats viel schneller als die räumlichen Schlüssel. (0,01 VS 0,001 in AVG)

Torben Brodt
quelle
1
Können Sie bitte Ihr Testergebnis hier mit Details versehen?
NameNotFoundException
4

MySQL verwendet double für alle Floats ... Verwenden Sie also type double. Die Verwendung von float führt in den meisten Situationen zu unvorhersehbaren gerundeten Werten

mlinuxgada
quelle
1
MySQL führt Operationen in ausDOUBLE . MySQL können Sie speichern Daten entweder als ein 4-Byte FLOAToder ein 8-Byte DOUBLE. Es ist also wahrscheinlich, dass beim Speichern eines Ausdrucks in einer FLOATSpalte ein Genauigkeitsverlust auftritt .
Rick James
4

Es ist zwar nicht für alle Vorgänge optimal, aber wenn Sie Kartenkacheln erstellen oder mit einer großen Anzahl von Markierungen (Punkten) mit nur einer Projektion arbeiten (z. B. Mercator, wie Google Maps und viele andere rutschige Karten-Frameworks erwarten), habe ich was gefunden Ich nenne "Vast Coordinate System", um wirklich sehr, sehr praktisch zu sein. Grundsätzlich speichern Sie die x- und y-Pixelkoordinaten in einer vergrößerten Richtung - ich verwende die Zoomstufe 23. Dies hat mehrere Vorteile:

  • Sie führen die teure Transformation von Lat / Lng zu Mercator-Pixel einmal durch, anstatt jedes Mal, wenn Sie den Punkt bearbeiten
  • Das Abrufen der Kachelkoordinate aus einem Datensatz bei einer bestimmten Zoomstufe erfordert eine Rechtsverschiebung.
  • Das Abrufen der Pixelkoordinate aus einem Datensatz erfordert eine Rechtsverschiebung und ein bitweises UND.
  • Die Verschiebungen sind so leicht, dass es praktisch ist, sie in SQL auszuführen. Dies bedeutet, dass Sie mit DISTINCT nur einen Datensatz pro Pixelposition zurückgeben können, wodurch die Anzahl der vom Backend zurückgegebenen Datensätze verringert wird, was weniger Verarbeitung auf dem Computer bedeutet Vorderes Ende.

Ich habe kürzlich in einem Blogbeitrag darüber gesprochen: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/

Kaitlin Duck Sherwood
quelle
4

Ich bin sehr überrascht von einigen Antworten / Kommentaren.

Warum um alles in der Welt sollte jemand bereit sein, die Genauigkeit freiwillig "vorab zu verringern" und später Berechnungen für die schlechteren Zahlen durchzuführen? Klingt letztendlich dumm.

Wenn die Quelle eine 64-Bit-Genauigkeit hat, wäre es sicherlich dumm, die Skalierung freiwillig auf z. 6 Dezimalstellen und beschränken Sie die Genauigkeit auf maximal 9 signifikante Stellen (was beim allgemein vorgeschlagenen Dezimalformat 9.6 der Fall ist).

Natürlich speichert man die Daten mit der Genauigkeit, die das Quellmaterial hat. Der einzige Grund, die Genauigkeit zu verringern, wäre begrenzter Speicherplatz.

  • Speichern Sie die Quellzahlen mit Originalgenauigkeit
  • Speichern Sie die aus der Quelle berechneten Zahlen in der Genauigkeit, in der die Berechnung erfolgt (z. B. wenn der Anwendungscode Doppelte verwendet, speichern Sie die Ergebnisse als Doppelte).

Das dezimale 9.6-Format verursacht ein Snap-to-Grid-Phänomen. Das sollte der allerletzte Schritt sein, wenn es überhaupt passieren soll.

Ich würde keine akkumulierten Fehler in mein Nest einladen.

Sturmwind
quelle
2
Weil die meisten GPS-Tools und -Anwendungen nur auf 6 Dezimalstellen genau sind. Es ist sinnlos, Daten mit einer höheren Genauigkeit zu speichern, als die Tools messen können. Gis.stackexchange.com/questions/8650/…
Yarin
1
@ Yarin Ja, aber Sie sprechen über Messungen und GPS, die in der Frage nicht erwähnt werden. Mit Sicherheit gibt es genauere Zahlen. Aber lassen Sie uns GPS betrachten; Angenommen, ein Quelldatensatz von 64-Bit-Floats enthält bereits eine Ungenauigkeit. 6 Dezimalstellen bedeuten, dass ein Breitengrad auf die nächsten ca. 11 Zentimeter eingestellt wird. Wenn Sie jetzt nur die Daten (mit 6 Dezimalstellen) speichern, können Sie eine mögliche Ungenauigkeit von 22 cm feststellen (wenn ursprünglich auch 11 cm). Freiwillig, wahrscheinlich, um eine 64-Bit-Berechnung durchzuführen, bevor möglicherweise ein drittes Mal gespeichert wird - jetzt 33 cm Ungenauigkeitsfenster, + -16 cm. Klingt dumm, imho.
Sturmwind
@ Rick James Ich würde es wahrscheinlich als 64-Bit speichern, dh. 0,333333333333333333. Wir reden über Geodaten, oder? "1/3" kommt in der Natur selten vor, wo Dinge normalerweise mit angemessener Genauigkeit gemessen werden.
Sturmwind
4

TL; DR

Verwenden Sie FLOAT (8,5), wenn Sie nicht in der NASA / im Militär arbeiten und keine Flugzeugnavigationssysteme herstellen.


Um Ihre Frage vollständig zu beantworten, müssen Sie verschiedene Dinge berücksichtigen:

Format

  • Grad Minuten Sekunden : 40 ° 26 '46 '' N 79 ° 58 '56' 'W.
  • Grad Dezimalminuten : 40 ° 26,767 'N 79 ° 58,933' W.
  • Dezimalgrad 1 : 40,446 ° N 79,982 ° W.
  • Dezimalgrad 2 : -32,60875, 21,27812
  • Ein anderes hausgemachtes Format? Niemand verbietet Ihnen, Ihr eigenes hauszentriertes Koordinatensystem zu erstellen und es als Kurs und Entfernung von Ihrem Zuhause zu speichern. Dies kann für bestimmte Probleme, an denen Sie arbeiten, sinnvoll sein.

Der erste Teil der Antwort wäre also: Sie können die Koordinaten in dem Format speichern, das Ihre Anwendung verwendet , um ständige Konvertierungen hin und her zu vermeiden und einfachere SQL-Abfragen durchzuführen.

Höchstwahrscheinlich verwenden Sie Google Maps oder OSM, um Ihre Daten anzuzeigen, und GMaps verwendet das Format "Dezimalgrad 2". So ist es einfacher, Koordinaten im selben Format zu speichern.

Präzision

Dann möchten Sie die Präzision definieren, die Sie benötigen. Natürlich können Sie Koordinaten wie "-32.608697550570334,21.278081997935146" speichern, aber haben Sie sich jemals um Millimeter gekümmert, während Sie zum Punkt navigieren? Wenn Sie nicht in der NASA arbeiten und keine Satelliten-, Raketen- oder Flugzeugflugbahnen ausführen, sollten Sie mit einer Genauigkeit von mehreren Metern in Ordnung sein.

Das häufig verwendete Format ist 5 Stellen nach Punkten, was eine Genauigkeit von 50 cm ergibt.

Beispiel : Zwischen X, 21.278081 8 und X, 21.278081 9 besteht ein Abstand von 1 cm . 7 Stellen nach dem Punkt ergeben also eine Genauigkeit von 1/2 cm und 5 Stellen nach dem Punkt ergeben eine Genauigkeit von 1/2 m (da der minimale Abstand zwischen verschiedenen Punkten 1 m beträgt und der Rundungsfehler nicht mehr als die Hälfte davon betragen kann). Für die meisten zivilen Zwecke sollte es ausreichen.

Das Grad-Dezimal-Minuten-Format (40 ° 26.767 ′ N 79 ° 58.933 ′ W) bietet genau die gleiche Genauigkeit wie 5 Stellen nach dem Punkt

Platzsparende Lagerung

Wenn Sie das Dezimalformat ausgewählt haben, ist Ihre Koordinate ein Paar (-32.60875, 21.27812). Offensichtlich reichen 2 x (1 Bit für Vorzeichen, 2 Stellen für Grad und 5 Stellen für Exponenten) aus.

Hier möchte ich Alix Axel aus Kommentaren unterstützen, die besagen, dass der Vorschlag von Google, es in FLOAT (10,6) zu speichern, wirklich extra ist, da Sie keine 4 Ziffern für den Hauptteil benötigen (da das Vorzeichen getrennt und der Breitengrad begrenzt ist bis 90 und der Längengrad ist auf 180 begrenzt). Sie können FLOAT (8,5) problemlos für eine Genauigkeit von 1 / 2m oder FLOAT (9,6) für eine Genauigkeit von 50 / 2cm verwenden. Oder Sie können lat und long sogar in getrennten Typen speichern, da FLOAT (7,5) für lat ausreicht. Siehe Referenz zu MySQL-Float-Typen . Jeder von ihnen ist wie normaler FLOAT und entspricht sowieso 4 Bytes.

Normalerweise ist Speicherplatz heutzutage kein Problem, aber wenn Sie den Speicher aus irgendeinem Grund wirklich optimieren möchten (Haftungsausschluss: Führen Sie keine Voroptimierung durch), können Sie lat (nicht mehr als 91 000 Werte + Vorzeichen) + long (Nr mehr als 181 000 Werte + Vorzeichen) auf 21 Bit, was deutlich weniger als 2xFLOAT (8 Bytes == 64 Bit) ist

Der Pate
quelle
3

Die räumlichen Funktionen in PostGIS sind viel funktionaler (dh nicht auf BBOX-Operationen beschränkt) als die in den räumlichen MySQL-Funktionen. Probieren Sie es aus: Linktext

Dylan
quelle
1
  1. Die Breiten reichen von -90 bis +90 (Grad), daher ist DECIMAL (10, 8) dafür in Ordnung

  2. Die Längen reichen von -180 bis +180 (Grad), daher benötigen Sie DECIMAL (11, 8).

Hinweis: Die erste Zahl ist die Gesamtzahl der gespeicherten Ziffern und die zweite die Zahl nach dem Dezimalpunkt.

Zusamenfassend: lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL

Mahfuz
quelle
0

Ich schlage vor, Sie verwenden den Float-Datentyp für SQL Server.

Anderson Ribeiro
quelle
-2

Lat Long-Berechnungen erfordern Genauigkeit. Verwenden Sie daher eine Art Dezimaltyp und stellen Sie die Genauigkeit mindestens 2 höher als die Zahl ein, die Sie speichern, um mathematische Berechnungen durchzuführen. Ich weiß nichts über meine SQL-Datentypen, aber in SQL Server verwenden die Leute häufig float oder real anstelle von dezimal und geraten in Schwierigkeiten, da es sich um geschätzte Zahlen handelt, die nicht real sind. Stellen Sie also sicher, dass der von Ihnen verwendete Datentyp ein echter Dezimaltyp und kein schwebender Dezimaltyp ist, und es sollte Ihnen gut gehen.

HLGEM
quelle
1
Sowohl Gleitkomma- als auch Dezimaltypen haben ihren Platz. Als Faustregel bedeutet Floats physikalische Variablen, und Dezimalstellen gelten für zählbare Einheiten (meistens Geld). Ich verstehe nicht, warum Sie Dezimal für Lat / Long bevorzugen
Javier
1
Ich denke auch, dass Float für Lat / Long in Ordnung ist. Zumindest unter SQL Server (4 Byte, 7 Ziffern).
Dragoljub Ćurčić
Float ist nicht genau, es wird geschätzt, See der Genauigkeit in einem Lat Long ist tödlich! Es könnte Sie auf einen völlig anderen Ort auf der Welt hinweisen.
HLGEM
2
Der maximale Fehler von Float-Datentypen ist so gering, dass dies kein Problem darstellen sollte. Ich meine, Sie müssen sich bei beiden Implementierungen sowieso der Fehlermultiplikation / -akkumulation bewusst sein.
Spidey
@HLGEM - Wenn Sie auf eine bestimmte Anzahl von Dezimalstellen runden, befinden Sie sich auch an einer anderen Stelle auf dem Globus. Die Frage ist, ob dieser andere Punkt so nah ist, dass es keine Rolle spielt.
Rick James
-3

A FLOATsollte Ihnen die erforderliche Präzision bieten und für Vergleichsfunktionen besser geeignet sein, als jede Koordinate als Zeichenfolge oder dergleichen zu speichern.

Wenn Ihre MySQL-Version älter als 5.0.3 ist, müssen Sie möglicherweise bestimmte Gleitkomma-Vergleichsfehler berücksichtigen .

Vor MySQL 5.0.3 speichern DECIMAL-Spalten Werte mit exakter Genauigkeit, da sie als Zeichenfolgen dargestellt werden. Berechnungen für DECIMAL-Werte werden jedoch mithilfe von Gleitkommaoperationen durchgeführt. Ab 5.0.3 führt MySQL DECIMAL-Operationen mit einer Genauigkeit von 64 Dezimalstellen aus, wodurch die häufigsten Ungenauigkeitsprobleme bei DECIMAL-Spalten gelöst werden sollten

ConroyP
quelle
2
Für eine einfache Berechnung benötigen Sie einen echten Breiten- / Längenkoordinatendatentyp. Stellen Sie sich die Bequemlichkeit von so etwas wie dem Äquivalent von "Wählen Sie * aus Geschäften vor, in denen die Entfernung (Speicherort, Standort) <5 Meilen"
Kirk Strauser
1
Hatte noch nie von den räumlichen Erweiterungen gehört, das klingt in Ordnung sehr praktisch, nachdem ich zuvor an einer geerbten App gearbeitet habe, die einige geobezogene Berechnungen durchführt, muss ich es überprüfen.
ConroyP
@ConroyP - Nein. In diesem Zitat wird darauf hingewiesen, dass DECIMAL(vor 5.0.3) bestimmte Fehler aufgrund der Verwendung der schwebenden Implementierung aufgetreten sind.
Rick James