495 Stimmen

Welches ist der ideale Datentyp für die Speicherung von Breiten- und Längengraden in einer MySQL-Datenbank?

In Anbetracht der Tatsache, dass ich Berechnungen auf Lat/Long-Paaren durchführen werde, welcher Datentyp ist am besten für die Verwendung mit einer MySQL-Datenbank geeignet?

7voto

The Godfather Punkte 3808

TL;DR

Verwenden Sie FLOAT(8,5), wenn Sie nicht für die NASA oder das Militär arbeiten und keine Navigationssysteme für Flugzeuge herstellen.


Um Ihre Frage vollständig zu beantworten, müssen Sie mehrere 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 heimatbezogenes Koordinatensystem zu erstellen und es als Richtung und Entfernung von Ihrem Zuhause zu speichern. Das könnte für bestimmte Probleme, an denen Sie arbeiten, sinnvoll sein.

Der erste Teil der Antwort lautet also: Sie können die Koordinaten in der Datei Format, das Ihre Anwendung verwendet um ständige Konvertierungen zu vermeiden und die SQL-Abfragen zu vereinfachen.

Wahrscheinlich verwenden Sie Google Maps oder OSM, um Ihre Daten anzuzeigen, und GMaps verwendet das Format "Dezimalgrad 2". Es wird also einfacher sein, die Koordinaten im gleichen Format zu speichern.

Präzision

Dann möchten Sie die benötigte Präzision definieren. Natürlich können Sie Koordinaten wie "-32.608697550570334,21.278081997935146" speichern, aber haben Sie sich schon einmal Gedanken über Millimeter bei der Navigation zum Punkt gemacht? Wenn Sie nicht bei der NASA arbeiten und sich nicht mit der Flugbahn von Satelliten, Raketen oder Flugzeugen beschäftigen, sollten Sie mit einer Genauigkeit von mehreren Metern auskommen.

Das übliche Format ist 5 Ziffern nach Punkten, was eine Genauigkeit von 50 cm ergibt.

Exemple 1cm Abstand zwischen X,21.278081 8 und X,21.278081 9 . 7 Ziffern nach dem Punkt ergeben also eine Genauigkeit von 1/2 cm und 5 Ziffern nach dem Punkt ergeben eine Genauigkeit von 1/2 m (da der Mindestabstand zwischen verschiedenen Punkten 1 m beträgt, kann der Rundungsfehler nicht mehr als die Hälfte davon betragen). Für die meisten zivilen Zwecke sollte dies ausreichend sein.

Das Format Grad-Dezimal-Minuten (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 gewählt haben, dann ist Ihre Koordinate ein Paar (-32.60875, 21.27812). Offensichtlich reicht 2 x (1 Bit für das Vorzeichen, 2 Ziffern für den Grad und 5 Ziffern für den Exponenten) aus.

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

Normalerweise ist Platz heutzutage kein Problem, aber wenn Sie die Speicherung aus irgendeinem Grund wirklich optimieren wollen (Haftungsausschluss: keine Voroptimierung), können Sie lat(nicht mehr als 91 000 Werte + Vorzeichen) + long(nicht mehr als 181 000 Werte + Vorzeichen) auf 21 Bits komprimieren, was bedeutet deutlich weniger als 2xFLOAT (8 Byte == 64 Bit)

6voto

mahfuz Punkte 1950
  1. Die Breitengrade reichen von -90 bis +90 (Grad), daher ist DECIMAL(10, 8) dafür geeignet.

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

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

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

6voto

Armfoot Punkte 4387

Aus einer ganz anderen und einfacheren Perspektive:

  • wenn Sie sich auf Google verlassen, um Ihre Karten, Markierungen, Polygone oder was auch immer anzuzeigen, dann lassen Sie die Berechnungen von Google durchführen!
  • sparen Sie Ressourcen auf Ihrem Server und speichern den Breiten- und Längengrad einfach zusammen als einen einzigen String ( VARCHAR ), z.B.: " -0000.0000001,-0000.000000000000001 " (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 Zeichenkette speichern lassen, nur für den Fall, dass Sie einige Fliegen oder Mikroben in der Zukunft ;
  • können Sie ihre Entfernungsmatrix oder ihre Geometrie-Bibliothek zur Berechnung von Entfernungen oder Erkennung von Punkten in bestimmten Bereichen mit einfachen Aufrufen wie diesem: google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • gibt es viele "serverseitige" APIs, die Sie verwenden können (in Python , Ruby on Rails , PHP , CodeIgniter , Laravel , Yii , Zend-Framework usw.), die Google Maps API verwenden.

Auf diese Weise müssen Sie sich nicht um die Indizierung von Zahlen und all die anderen Probleme kümmern, die mit Datentypen verbunden sind und Ihre Koordinaten durcheinander bringen können.

5voto

Es ist zwar nicht optimal für alle Operationen, aber wenn Sie Kartenkacheln erstellen oder mit einer großen Anzahl von Markern (Punkten) mit nur einer Projektion arbeiten (z. B. Mercator, wie Google Maps und viele andere Slippy-Maps-Frameworks es erwarten), habe ich festgestellt, dass das, was ich "Vast Coordinate System" nenne, sehr, sehr praktisch ist. Im Grunde speichert man die x- und y-Pixelkoordinaten in einer bestimmten Vergrößerungsstufe - ich verwende Zoomstufe 23. Dies hat mehrere Vorteile:

  • Sie tun die teure lat/lng zu mercator Pixel Transformation einmal statt jedes Mal, wenn Sie den Punkt behandeln
  • Um die Kachelkoordinate eines Datensatzes mit einer bestimmten Zoomstufe zu erhalten, ist eine Rechtsverschiebung erforderlich.
  • Um die Pixelkoordinaten aus einem Datensatz zu erhalten, ist eine Rechtsverschiebung und ein bitweises UND erforderlich.
  • Die Verschiebungen sind so leichtgewichtig, dass es praktisch ist, sie in SQL durchzuführen, was bedeutet, dass Sie ein DISTINCT durchführen können, um nur einen Datensatz pro Pixelposition zurückzugeben, was die Anzahl der vom Backend zurückgegebenen Datensätze reduziert, was weniger Verarbeitung am Frontend bedeutet.

Über all dies habe ich in einem kürzlich erschienenen Blogbeitrag gesprochen: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/

4voto

mlinuxgada Punkte 578

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X