¿Cuál es el tipo de datos ideal para usar cuando se almacena la latitud / longitud en una base de datos MySQL?

StackOverflow https://stackoverflow.com/questions/159255

Pregunta

Teniendo en cuenta que realizaré cálculos en pares lat / largos, ¿qué tipo de datos es el más adecuado para usar con una base de datos MySQL?

¿Fue útil?

Solución

Utilice extensiones espaciales de MySQL con GIS.

Otros consejos

Google proporciona una solución PHP / MySQL de principio a fin para un ejemplo " Localizador de tiendas " Aplicación con Google Maps. En este ejemplo, almacenan los valores de lat / lng como " Flotante " con una longitud de " 10,6 "

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

Básicamente, depende de la precisión que necesite para sus ubicaciones. Usando DOBLE tendrás una precisión de 3.5nm. DECIMAL (8,6) / (9,6) baja a 16cm. FLOTADOR es de 1,7 m ...

Esta tabla muy interesante tiene una lista más completa: 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

Espero que esto ayude.

Las Extensiones espaciales de MySQL son la mejor opción porque tiene la lista completa de operadores e índices espaciales a su disposición. Un índice espacial le permitirá realizar cálculos basados ??en la distancia muy rápidamente. Tenga en cuenta que, a partir de la versión 6.0, la extensión espacial aún está incompleta. No voy a dejar de lado MySQL Spatial, solo te hago saber las trampas antes de que llegues demasiado lejos en esto.

Si está tratando estrictamente con puntos y solo con la función DISTANCIA, esto está bien. Si necesita realizar cálculos con polígonos, líneas o puntos de búfer, los operadores espaciales no proporcionan resultados exactos a menos que use el " relato " operador. Vea la advertencia en la parte superior de 21.5.6 . Las relaciones tales como contiene, dentro o intersecciones están usando el MBR, no la forma geométrica exacta (es decir, una Elipse se trata como un Rectángulo).

Además, las distancias en MySQL Spatial están en las mismas unidades que su primera geometría. Esto significa que si está utilizando grados decimales, entonces sus medidas de distancia están en grados decimales. Esto hará que sea muy difícil obtener resultados exactos al obtener furthur del ecuador.

Cuando hice esto para una base de datos de navegación construida a partir de ARINC424 hice una buena cantidad de pruebas y mirando el código, utilicé un DECIMAL (18,12) (en realidad un NUMERIC (18,12) porque era firebird ).

Los flotantes y los dobles no son tan precisos y pueden dar como resultado errores de redondeo que pueden ser algo muy malo. No recuerdo si encontré algún dato real que tuviera problemas, pero estoy bastante seguro de que la incapacidad de almacenar con precisión en una flotación o un doble podría causar problemas

El punto es que al usar grados o radianes, conocemos el rango de los valores, y la parte fraccionaria necesita la mayoría de los dígitos.

Las MySQL Spatial Extensions son una buena alternativa porque siguen El Modelo de Geometría de OpenGIS . No los usé porque necesitaba mantener mi base de datos portátil.

Depende de la precisión que requiera.

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

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

Para resumir:

  • La opción disponible más precisa es DOUBLE .
  • El tipo visto más comúnmente utilizado es DECIMAL (8,6) / (9,6) .

A partir de MySQL 5.7 , considere usar Tipos de datos patológicos (SDT), específicamente POINT para almacenar una sola coordenada. Antes de 5.7, SDT no admite índices (con excepción de 5.6 cuando el tipo de tabla es MyISAM).

Nota:

Basado en este artículo de wiki http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy el tipo de datos apropiado en MySQL es decimal (9,6) para almacenar la longitud y latitud en campos separados.

Utilice DECIMAL (8,6) para la latitud (90 a -90 grados) y DECIMAL (9,6) para la longitud (180 a -180 grados). 6 decimales están bien para la mayoría de las aplicaciones. Ambos deben estar " firmados " para permitir valores negativos.

No es necesario ir muy lejos, de acuerdo con Google Maps, lo mejor es FLOAT (10,6) para latencia y lng.

Almacenamos la latitud / longitud X 1,000,000 en nuestra base de datos de Oracle como NÚMEROS para evitar errores de redondeo con dobles.

Dado que la latitud / longitud hasta el sexto lugar decimal fue de 10 cm de precisión, eso era todo lo que necesitábamos. Muchas otras bases de datos también almacenan lat / long hasta el sexto lugar decimal.

En una perspectiva completamente diferente y más simple:

De esta manera, no necesita preocuparse por la indexación de números y todos los demás problemas asociados con los tipos de datos que pueden arruinar sus coordenadas.

dependiendo de su aplicación, sugiero usar FLOAT (9,6)

las claves espaciales le darán más características, pero en los puntos de referencia de producción, los flotantes son mucho más rápidos que las claves espaciales. (0,01 VS 0,001 en AVG)

MySQL usa el doble para todos los flotadores ... Así que usa el tipo doble. El uso de float conducirá a valores redondeados impredecibles en la mayoría de las situaciones

Si bien no es óptimo para todas las operaciones, si está haciendo mosaicos de mapas o trabajando con un gran número de marcadores (puntos) con una sola proyección (por ejemplo, Mercator, como Google Maps y muchos otros marcos de mapas de mapas deslizantes), encontrado lo que yo llamo " Vast Coordinate System " para ser realmente, muy práctico. Básicamente, almacena las coordenadas de píxeles x e y de alguna manera. Uso el nivel de zoom 23. Esto tiene varias ventajas:

  • Realiza la costosa transformación de píxeles lat / lng a mercator una vez en lugar de cada vez que maneja el punto
  • Obtener la coordenada de mosaico de un registro dado un nivel de zoom tiene un desplazamiento hacia la derecha.
  • Obtener la coordenada de píxel de un registro requiere un desplazamiento a la derecha y otro a modo de bit AND
  • Los turnos son tan ligeros que es práctico hacerlos en SQL, lo que significa que puede hacer un DISTINTO para devolver solo un registro por ubicación de píxeles, lo que reducirá el número de registros devueltos por el servidor, lo que significa menos Procesamiento en la parte frontal.

Hablé de todo esto en una publicación reciente del blog:     http://blog.webfoot.com/2013/03/ 12 / optimizing-map-tile-generation /

Estoy muy sorprendido por algunas respuestas / comentarios.

¿Por qué demonios alguien estaría dispuesto a voluntaré " reducir previamente " La precisión, y luego realizar cálculos en los peores números? Suena en última instancia estúpido.

Si la fuente tiene una precisión de 64 bits, ciertamente sería tonto arreglar voluntariamente la escala, por ejemplo. 6 decimales, y limita la precisión a un máximo de 9 excavaciones significativas (lo que ocurre con el formato decimal 9.6 comúnmente propuesto).

Naturalmente, uno almacena los datos con la precisión que tiene el material de origen. La única razón para disminuir la precisión sería el espacio de almacenamiento limitado.

  • Almacene las figuras de origen con precisión original
  • Almacene las cifras calculadas desde la fuente en la precisión con la que se realiza el cálculo (por ejemplo, si el código de la aplicación utiliza dobles, almacene los resultados como dobles)

El formato decimal 9.6 causa un fenómeno de snap-to-grid. Ese debería ser el último paso, si es que tiene que suceder.

No invitaría los errores acumulados a mi nido.

Las funciones espaciales en PostGIS son mucho más funcionales (es decir, no están limitadas a las operaciones de BBOX) que las funciones espaciales de MySQL. Compruébelo: texto del enlace

TL;DR

Use FLOAT (8,5) si no está trabajando en NASA / military y no está haciendo sistemas de navegación aérea.


Para responder completamente a tu pregunta, deberías considerar varias cosas:

Formato

  • grados minutos segundos : 40 ° 26 ' 46 "N 79 ° 58 ' 56" W
  • grados minutos decimales : 40 ° 26.767 ' N 79 ° 58.933 ' W
  • grados decimales 1 : 40.446 ° N 79.982 ° W
  • grados decimales 2 : -32.60875, 21.27812
  • ¿Algún otro formato hecho en casa? Nadie le prohíbe crear su propio sistema de coordenadas centrado en el hogar y almacenarlo como rumbo y distancia desde su hogar. Esto podría tener sentido para algunos problemas específicos en los que está trabajando.

Entonces, la primera parte de la respuesta sería: puede almacenar las coordenadas en el formato que utiliza su aplicación para evitar conversiones constantes de un lado a otro y hacer consultas SQL más simples.

Lo más probable es que use Google Maps u OSM para mostrar sus datos, y GMaps está usando " grados decimales 2 " formato. Por lo tanto, será más fácil almacenar las coordenadas en el mismo formato.

Precisión

Entonces, le gustaría definir la precisión que necesita. Por supuesto, puede almacenar coordenadas como " -32.608697550570334,21.278081997935146 " ;, pero ¿alguna vez le importaron los milímetros mientras navega al punto? Si no estás trabajando en la NASA y no estás haciendo satélites, cohetes o trayectorias de aviones, deberías estar bien con una precisión de varios metros.

El formato utilizado comúnmente es de 5 dígitos después de los puntos, lo que le proporciona una precisión de 50 cm.

Ejemplo : hay 1 cm de distancia entre X, 21.278081 8 y X, 21.278081 9 . Por lo tanto, 7 dígitos después del punto le dan una precisión de 1/2 cm y 5 dígitos después del punto le dará una precisión de 1/2 metro (porque la distancia mínima entre puntos distintos es de 1 m, por lo que el error de redondeo no puede ser más de la mitad). Para la mayoría de los propósitos civiles debería ser suficiente.

El formato de minutos decimales de

(40 ° 26.767 ' N 79 ° 58.933 ' W) le da exactamente la misma precisión que 5 dígitos después del punto

Almacenamiento eficiente en espacio

Si ha seleccionado el formato decimal, entonces su coordenada es un par (-32.60875, 21.27812). Obviamente, 2 x (1 bit para signo, 2 dígitos para grados y 5 dígitos para exponente) serán suficientes.

Así que aquí me gustaría respaldar a Alix Axel de los comentarios que dicen que la sugerencia de Google para almacenarlo en FLOAT (10,6) es realmente extra, porque no necesita 4 dígitos para la pantalla principal. parte (ya que el signo está separado y la latitud está limitada a 90 y la longitud está limitada a 180). Puede usar fácilmente FLOAT (8,5) para una precisión de 1 / 2m o FLOAT (9,6) para una precisión de 50 / 2cm. O incluso puede almacenar lat y long en tipos separados, porque FLOAT (7,5) es suficiente para lat. Consulte los tipos de flotador de MySQL reference . Cualquiera de ellos será como FLOAT normal y igual a 4 bytes.

Por lo general, el espacio no es un problema en la actualidad, pero si realmente desea optimizar el almacenamiento por algún motivo (Descargo de responsabilidad: no realice la optimización previa), puede comprimir lat (no más de 91 000 valores + signo) + largo (no más de 181 000 valores + signo) a 21 bits, que es significativamente menor que 2xFLOAT (8 bytes == 64 bits)

  1. Las latitudes van desde -90 a +90 (grados), por lo que DECIMAL (10, 8) está bien para eso

  2. las longitudes varían de -180 a +180 (grados), por lo que necesita DECIMAL (11, 8).

Nota: El primer número es el número total de dígitos almacenados, y el segundo es el número después del punto decimal.

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

Los cálculos de latitud larga requieren precisión, así que use algún tipo de tipo decimal y haga que la precisión sea al menos 2 más alta que la cantidad que almacenará para realizar cálculos matemáticos. No sé acerca de los tipos de datos de mi sql, pero en el servidor SQL la gente a menudo usa float o real en lugar de decimal y se mete en problemas porque estos son números estimados no reales. Así que solo asegúrate de que el tipo de datos que usas sea un tipo decimal verdadero y no un tipo decimal flotante y estarás bien.

A FLOAT debería darle toda la precisión que necesita, y ser mejor para las funciones de comparación que almacenar cada coordenada como una cadena o similar.

Si su versión de MySQL es anterior a 5.0.3, es posible que deba prestar atención a cierto errores de comparación de punto flotante sin embargo.

  

Antes de MySQL 5.0.3, las columnas DECIMAL almacenan los valores con precisión exacta porque se representan como cadenas, pero los cálculos sobre los valores DECIMAL se realizan mediante operaciones de punto flotante. A partir de la versión 5.0.3, MySQL realiza operaciones DECIMAL con una precisión de 64 dígitos decimales, lo que debería resolver los problemas más comunes de imprecisión cuando se trata de columnas DECIMAL

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top