Was ist der ideale Datentyp zu verwenden, wenn in einer MySQL-Datenbank Breite / Länge zu speichern?
-
03-07-2019 - |
Frage
Bedenkt man, dass ich Berechnungen auf lat / long Paaren würde durchgeführt wird, welcher Datentyp am besten geeignet ist für die Verwendung mit einer MySQL-Datenbank?
Lösung
Verwenden von MySQL mit GIS .
Andere Tipps
Google stellt eine Start PHP / MySQL Lösung für ein Beispiel "Store Locator" Anwendung mit Google Maps zu beenden. 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
Im Grunde kommt es auf die Präzision, die Sie für Ihre Standorte benötigen. Mit DOUBLE finden Sie eine 3,5 nm Präzision haben. DECIMAL (8,6) / (9,6) geht bis zu 16cm. FLOAT ist 1.7m ...
Diese sehr interessante Tabelle hat eine ausführlichere 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
Hope, das hilft.
MySQL Spatial Extensions sind die beste Option, weil Sie die vollständige Liste der räumlichen Operatoren und Indizes zur Verfügung haben. Ein räumlicher Index ermöglicht es Ihnen, abstandsbasierte Berechnungen sehr schnell durchzuführen. Bitte beachten Sie, dass ab 6.0, die räumliche Ausdehnung noch nicht abgeschlossen ist. Ich bin nicht MySQL Spatial Niederschlagung, nur dass Sie die Gefahren wissen, bevor Sie zu weit auszukommen zu diesem Thema.
Wenn Sie sind streng mit Punkten und nur die Entfernung Funktion zu tun, das ist in Ordnung. Wenn Sie Berechnungen mit Polygonen tun müssen, Linien, oder Buffered-Points, die räumlichen Operatoren bieten keine genauen Ergebnisse, wenn Sie den „bezieht“ Operator verwenden. Siehe die Warnung an der Spitze der
Als ich das von ARINC424 gebaut für eine Navigationsdatenbank habe ich eine ganze Menge Tests haben und zurück Blick auf den Code, habe ich eine DECIMAL (18,12) (Eigentlich ein numerisches (18,12), weil es war Feuervogel ). Floats und Doppelzimmer sind nicht so präzise und führen Fehler in Runden, die eine sehr schlechte Sache sein kann. Ich kann mich nicht erinnern, ob ich ein wirklichen Daten gefunden, die Probleme hatten - aber ich bin ziemlich sicher, dass die Unfähigkeit, in einem Schwimmer genau zu speichern oder ein Doppel könnte zu Problemen führen, Der Punkt ist, dass, wenn Grad oder Radiant verwenden wir den Bereich der Werte kennen - und der Bruchteil benötigt die Ziffern Die MySQL Spatial Extensions eine gute Alternative denn sie folgen Die OpenGIS Geometrie Modell. Ich habe sie nicht benutzen, weil ich brauchte, um meine Datenbank tragbar zu halten.
Abhängig von der Genauigkeit, 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
Um es zusammenzufassen:
- Die präziseste verfügbare Option ist
DOUBLE
. - Die am häufigsten verwendeten gesehen Typ ist
DECIMAL(8,6)/(9,6)
.
Wie von MySQL 5.7 , sollten Sie mit Spatial Datentypen (SDT), insbesondere POINT
für eine einzelne Koordinate speichert. Vor 5.7, ist SDT nicht Indizes unterstützt (mit Ausnahme von 5,6, wenn Tabellentyp MyISAM ist).
Hinweis:
- Wenn
POINT
Klasse verwendet, muss die Reihenfolge der Argumente für die Speicherung von KoordinatenPOINT(latitude, longitude)
werden. - Es gibt eine spezielle Syntax für einen räumlichen Index erstellen .
- Der größte Vorteil SDT der Verwendung ist, dass Sie den Zugriff auf Räumliche Funktionen Analysiert , zB Berechnen Abstand zwischen zwei Punkten (
ST_Distance
) und Bestimmen, ob ein Punkt in einem anderen Bereich (ST_Contains
).
Basierend auf diesem Wiki-Artikel http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy der entsprechende Datentyp in MySQL ist Decimal (9,6) zum Speichern das Längen- und Breitengrade in separate Felder.
Verwendung DECIMAL(8,6)
für die Breite (90 bis -90 Grad) und DECIMAL(9,6)
zur Länge (180 bis -180 Grad). 6 Dezimalstellen ist in Ordnung für die meisten Anwendungen. Beide sollten „unterzeichnet“ werden für negative Werte zu ermöglichen.
Keine Notwendigkeit zu weit gehen, nach Google Maps ist die beste FLOAT (10,6) für lat und lng.
Wir speichern Breite / Länge X 1.000.000 in unserer Oracle-Datenbank als ZAHLEN off Fehler mit Doppel zu vermeiden Runde.
Da Breite / Länge bis 6. Nachkommastelle betrug 10 cm Genauigkeit, das war alles was wir brauchten. Viele andere Datenbanken auch lat speichern / lang bis 6. Nachkommastelle.
In einer ganz anderen und einfacheren Perspektive:
- Wenn Sie auf Google setzen für das Zeigen Sie Ihre Karten, Marker, Polygone, was auch immer, dann werden die Berechnungen von Google durchgeführt werden lassen!
- Sie sparen Ressourcen auf Ihrem Server und Sie einfach speichern Sie die geografische Breite und Länge zusammen als eine einzige Zeichenfolge (
VARCHAR
), zB: „ - 0.000,0000001, -0.000,000000000000001 “(35 Länge, und wenn eine Zahl von mehr als 7 hat Dezimalziffern dann wird es aufgerundet); - , wenn Google mehr als 7 Dezimalstellen pro Zahl zurückgibt, können Sie sich das sowieso in der Zeichenfolge gespeicherten Daten, falls Sie einige flieht oder Mikroben in Zukunft ;
- Sie können ihre Distanzmatrix oder ihre Geometriebibliothek für Entfernungen oder Erfassungspunkte in bestimmten Bereichen mit Anrufen so einfach wie diese:
google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
- gibt es viele "serverseitige" APIs Sie (in Python , Ruby on Rails , PHP , CodeIgniter , Laravel , Yü ,
auf Ihnen je nach Anwendung, ich schlage vor, mit FLOAT (9,6)
räumliche Tasten werden Sie mehr Funktionen geben, aber in durch Produktion Benchmarks sind die Schwimmer viel schneller als die räumlichen Tasten. (0,01 VS 0.001 in AVG)
MySQL verwendet Doppel für alle Schwimmer ... So Typ double verwenden. Mit Schwimmer wird in den meisten Fällen zu unvorhersehbaren gerundeten Werten führen
Es ist zwar nicht optimal für alle Operationen ist, wenn Sie Kartenkacheln machen oder die Arbeit mit einer großen Anzahl von Markierungen (Punkte) mit nur einem Vorsprung (zB Mercator, wie Google Maps und viele andere slippy Karten Frameworks erwarten), I hat herausgefunden, was ich „Vast Koordinatensystem“ nennen, wirklich zu sein, wirklich praktisch. Grundsätzlich speichern Sie x und y Pixelkoordinaten auf irgendeine Weise gezoomten-in - ich Zoomstufe 23. Dies hat mehrere Vorteile:
- Sie tun Transformation, die teure lat / lng zu mercator Pixel einmal statt jedes Mal wenn Sie den Punkt behandeln
- Getting die Kachel aus einem Datensatz einer Zoomstufe gegebenen Koordinate nimmt eine Verschiebung nach rechts.
- Ankommen koordinieren das Pixel aus einem Datensatz nimmt eine Verschiebung nach rechts und eine bitweise AND.
- Die Verschiebungen sind so leicht, dass es praktisch ist sie in SQL zu tun, was bedeutet, dass Sie eine DISTINCT tun können nur einen Datensatz pro Pixelposition zurückzukehren, die vom Backend zurück auf der Anzahl Datensätze abgeholzt werden, was bedeutet, weniger Verarbeitung auf dem vorderen Ende.
Ich sprach über all dies kürzlich in einem Blog-Post: http://blog.webfoot.com/2013/03/ 12 / Optimierung-map-Kachel-Generation /
Ich bin sehr überrascht von einigen Antworten / Kommentare.
Warum in aller Welt sollte jemand bereit sein, „pre-Abnahme“, um die Präzision zu voluntarely, und dann später auf Berechnungen auf den schlechteren Zahlen? Hört sich letztlich dumm.
Wenn die Quelle 64-Bit-Genauigkeit hat, sicherlich wäre es dumm voluntarely die Waage zB zu beheben. 6 Dezimalzahlen, und begrenzt die Genauigkeit bis zu einem Maximum von 9 signifikanter digts (die mit dem üblicherweise vorgeschlagenen decimal 9.6 Format passiert).
Natürlich speichert man die Daten mit der Präzision, die das Ausgangsmaterial aufweist. Der einzige Grund, Präzision zu verringern würde Speicherplatz begrenzt werden.
- Shop Quelle Zahlen mit Original-Genauigkeit
- Shop Zahlen aus der Quelle in der Genauigkeit berechnet die Berechnung geschieht (z. B. wenn der aplication Code verdoppelt verwendet, speichern Sie die Ergebnisse als verdoppelt)
Die Dezimalstelle 9.6-Format führt zu einem snap-to-grid phenomen. Das sollte der letzte Schritt sein, wenn es überhaupt geschehen.
Ich würde nicht akkumulierten Fehler zu meinem Nest einladen.
Die räumlichen Funktionen in PostGIS sind viel mehr funktionelle (d.h. nicht auf BBOX Operationen beschränkt) als die in den MySQL räumlichen Funktionen. Check it out: Link-Text
TL; DR
Mit FLOAT (8,5), wenn Sie nicht arbeiten in NASA / Militär und nicht die Flugzeuge navi Systeme.
Ihre Frage vollständig zu beantworten, sollten Sie einige Dinge berücksichtigen müssen:
Format
- Grad Minuten Sekunden 40 ° 26 '46 "N 79 ° 58' 56" W
- Dezimalgraden Minuten : 40 ° 26,767 'N 79 ° 58,933' W
- Dezimalgraden 1 : 40,446 ° N 79,982 ° W
- Dezimalgraden 2 : -32,60875, 21,27812
- Einige andere hausgemachte Format? Noone verbietet Sie von Ihrem eigenen vier Wänden zentrierten Koordinatensystem zu machen und speichern Sie es als Überschrift und die Entfernung von zu Hause aus. Dies könnte Sinn für einige spezifische Probleme machen Sie gerade arbeiten.
So ist der erste Teil der Antwort sei -. Sie die Koordinaten speichern können in dem formatieren Sie Ihre Anwendung verwendet konstante Umwandlungen vermeiden hin und her und einfache SQL-Abfragen macht
Die meisten wahrscheinlich verwenden Sie Google Maps oder OSM Daten anzuzeigen, und GMaps verwenden „Dezimalgraden 2“ -Format. So wird es einfacher sein, Koordinaten zu speichern, im gleichen Format.
Precision
Dann möchten Sie Präzision definieren, die Sie benötigen. Natürlich können Sie Koordinaten speichern, wie „-32.608697550570334,21.278081997935146“, haben aber über Millimetern während der Navigation auf den Punkt, den Sie jemals betreut? Wenn Sie nicht in der NASA arbeiten und nicht zu tun, Satelliten oder Raketen oder Flugzeuge Trajektorien, sollten Sie mit mehreren Metern Genauigkeit in Ordnung sein.
Häufig verwendete Format ist 5 Stellen nach Punkten, die Sie 50 cm Genauigkeit gibt.
Beispiel : es gibt 1cm Abstand zwischen X, 21,278081 8 und X, 21,278081 9 . So 7 Stellen nach Punkt geben Ihnen 1 / 2cm Präzision und 5 Stellen nach dem Punkt geben Ihnen 1/2 Meter Genauigkeit (weil minimaler Abstand zwischen verschiedenen Punkten 1m ist, so Rundungsfehler kann nicht mehr als die Hälfte davon sein). Für die meisten zivilen Zwecke sollte es genug sein.
Dezimalgraden Minuten-Format (40 ° 26,767 'N 79 ° 58,933' W) gibt Ihnen genau die gleiche Präzision wie 5 Stellen nach dem Punkt
Platzsparend Lagerung
Wenn Sie Dezimalformat ausgewählt haben, dann koordinieren Sie ist ein Paar (-32,60875, 21,27812). Offensichtlich 2 x (1 Bit für das Vorzeichen, 2 Ziffern für Grad und 5 Stellen für Exponenten) ausreicht.
hier So würde Ich mag unterstützen Alix Axel aus den Kommentaren sagen, dass Google Vorschlag, es in FLOAT zu speichern (10,6) ist wirklich besonders, weil Sie für Haupt nicht 4 Stellen müssen Teil (da Zeichen wird abgetrennt und Breite ist begrenzt auf 90 und Länge ist begrenzt auf 180). Sie können ganz einfach FLOAT (8,5) verwenden für 1 / 2m Präzision oder FLOAT (9,6) für 50 / 2cm Präzision. Oder Sie können auch speichern lat und lange in getrennten Typen, weil FLOAT (7,5) genug für lat ist. Siehe MySQL Typen float Referenz . Alle von ihnen werden wie normale FLOAT und gleich 4 Bytes sowieso.
In der Regel ist der Raum kein Problem heutzutage, aber wenn Sie wirklich wollen, um den Speicher aus irgendeinem Grunde (Disclaimer: Sie Voroptimierung nicht tun) zu optimieren, können Sie komprimieren lat (nicht mehr als 91 000 Werte + Zeichen) + lang (nicht mehr als 181 000 Werte + Zeichen) zu 21 Bits, was deutlich weniger als 2xFLOAT (8 Byte == 64 Bit)
-
Latitudes Bereich von -90 bis +90 (Grad), so DECIMAL (10, 8) ist, dass für ok
-
Längenbereich von -180 bis +180 (Grad), so dass Sie benötigen DECIMAL (11, 8).
Hinweis: Die erste Zahl ist die Gesamtzahl der Stellen gespeichert sind, und die zweite ist die Zahl nach dem Komma
. Kurz gesagt: lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL
Lat Long Berechnungen erfordern Präzision, so eine Art von Dezimal-Typ verwenden und die Genauigkeit mindestens 2 höher als die Zahl machen Sie, um gespeichert werden mathematische Berechnungen durchführen. Ich weiß nicht, über die meine SQL-Datentypen, aber in SQL Server Menschen oft float oder real statt dezimal und in Schwierigkeiten geraten, weil diese Zahlen sind Schätzungen zufolge nicht reale. Also nur sicherstellen, dass der Datentyp Sie verwenden, ist ein wahrer dezimal Typ und keine Gleitkommadatentyp Typ, und Sie sollten in Ordnung sein.
Es sollte eine FLOAT
geben Sie alle die Präzision, die Sie benötigen, und für Vergleichsfunktionen besser als jede Koordinate als String oder dergleichen zu speichern.
Wenn Ihre MySQL-Version älter als 5.0.3 ist, können Sie Beachtung bestimmter Gleitkomma-Vergleichsfehler jedoch.
Vor MySQL 5.0.3, DECIMAL Spalten speichern Werte mit einer exakten Genauigkeit, weil sie als Zeichenfolgen dargestellt, aber Berechnungen auf Dezimalwerte werden fertig mit Gleitkommaoperationen. Ab 5.0.3, führt MySQL DECIMAL Operationen mit einer Genauigkeit von 64 Dezimalstellen, die häufigste Ungenauigkeit Probleme lösen soll, wenn es darum geht, Spalt DECIMAL