Qual é o tipo de dados ideal para usar quando armazenar latitude / longitude em um banco de dados MySQL?

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

Pergunta

Tendo em conta que eu estarei efectuar cálculos sobre Lat Long pares /, que tipo de dados é mais adequado para uso com um banco de dados MySQL?

Foi útil?

Solução

Usar MySQL espacial extensões com GIS.

Outras dicas

O Google fornece um início ao fim solução PHP / MySQL para um exemplo "Store Locator" aplicação com o Google Maps. Neste exemplo, eles armazenam os valores / GNL lat como "Float" com um comprimento de "10,6"

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

Basicamente, ele depende da precisão que você precisa para seus locais. Usando DUPLO você vai ter uma precisão 3.5nm. DECIMAL (8,6) / (9,6) desce para 16 centímetros. FLOAT é 1.7m ...

Esta tabela muito interessante tem uma lista mais completa: http://mysql.rjweb.org/ doc.php dentro / 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 isso ajude.

Extensões Espacias do MySQL são a melhor opção, porque você tem a lista completa de operadores espaciais e índices à sua disposição. Um índice espacial irá permitir-lhe realizar cálculos com base na distância muito rapidamente. Tenha em mente que a partir de 6.0, a extensão espacial ainda está incompleta. Não estou colocando para baixo MySQL espacial, única permitindo que você sabe das armadilhas antes de chegar longe demais sobre isso.

Se você está lidando estritamente com pontos e somente a função de distância, isso é bom. Se você precisa fazer quaisquer cálculos com polígonos, linhas ou Protegido-Pontos, os operadores espaciais não fornecem resultados exatos menos que você use o operador "relacionar". Veja o aviso na parte superior de 21.5.6 . Relações tais como contém, dentro, ou intersecta a utilizar o MBR, não a forma geometria exacta (isto é, uma elipse é tratado como um retângulo).

Além disso, as distâncias em MySQL espacial estão nas mesmas unidades que sua primeira geometria. Isto significa que se você estiver usando graus decimais, então suas medidas de distância estão em graus decimais. Isto tornará muito difícil obter resultados exatos que você começa furthur do equador.

Quando eu fiz isso para um banco de dados de navegação construído a partir ARINC424 eu fiz uma quantidade justa de testar e olhando para o código, eu usei um DECIMAL (18,12) (Na verdade, um numérico (18,12), porque ele firebird foi ).

flutua e duplas não são tão precisos e podem resultar em erros de arredondamento que pode ser uma coisa muito ruim. Não me lembro se eu encontrar quaisquer dados reais que tiveram problemas - mas estou bastante certo de que a incapacidade para armazenar com precisão em uma bóia ou uma dupla poderia causar problemas

O ponto é que, ao usar graus ou radianos sabemos que o intervalo de valores -. E a parte fracionária precisa de mais dígitos

O MySQL espacial extensões são uma boa alternativa porque seguem O OpenGIS Geometry Modelo . Eu não usá-los porque eu precisava manter a minha base de dados portátil.

depende da precisão que você precisa.

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:

  • A opção mais preciso disponível é DOUBLE.
  • O tipo mais visto comum usado é DECIMAL(8,6)/(9,6).

Como de MySQL 5.7 , considere o uso de Spatial dados (SDT), especificamente POINT para armazenar uma única coordenada. Antes de 5.7, SDT não suporta índices (com exceção de 5,6 quando o tipo de tabela é MyISAM).

Nota:

Com base neste artigo wiki http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy o tipo de dados adequado no MySQL é Decimal (9,6) para armazenar a longitude e latitude na campos separados.

Use DECIMAL(8,6) de latitude (90 a -90 graus) e DECIMAL(9,6) de longitude (180 a -180 graus). 6 casas decimais é muito bem para a maioria das aplicações. Ambos devem ser "assinado" para permitir que para valores negativos.

Não é preciso ir muito longe, de acordo com o Google Maps, o melhor é FLOAT (10,6) para GNL lat e.

Nós armazenar latitude / longitude X 1.000.000 em nosso banco de dados Oracle como números para evitar erros fora redondas com duplos.

Dado que latitude / longitude para o 6º lugar decimal era 10 centímetros de precisão que era tudo o que precisávamos. Muitos outros bancos de dados também armazenar latitude / longitude para o 6º lugar decimal.

Em uma perspectiva completamente diferente e mais simples:

  • Se você está confiando em Google para mostrar os seus mapas, marcadores, polígonos, qualquer que seja, então deixe os cálculos ser feito pelo Google!
  • você economizar recursos em seu servidor e você simplesmente armazenar a latitude e longitude juntos como uma única string (VARCHAR), ex: " - 0.000,0000001, -0.000,000000000000001 "(35 comprimento e se um número tem mais de 7 dígitos decimais então fica arredondado);
  • Se o Google retorna mais de 7 dígitos decimais por número, você pode obter os dados armazenados em sua seqüência de qualquer maneira, apenas no caso de você deseja detectar alguns foge ou micróbios no futuro ;
  • você pode usar seu matriz de distância ou a sua geometria biblioteca para calcular distâncias ou detecção de pontos em determinadas áreas com chamadas tão simples como isto: google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • há uma abundância de "server-side" APIs que você pode usar (em Python , ruby ??on Rails , PHP , CodeIgniter , Laravel , Yii , Zend Framework , etc.) que o uso do Google Maps API.

Desta forma, você não precisa se preocupar com números de indexação e todos os outros problemas associados com os tipos de dados que podem estragar suas coordenadas.

dependendo de sua aplicação, eu sugiro usar FLOAT (9,6)

chaves espaciais lhe dará mais recursos, mas em pela produção benchmarks os carros alegóricos são muito mais rápidos do que as chaves espaciais. (0,01 VS 0001 no AVG)

O MySQL usa dupla para todos os carros alegóricos ... Assim, tipo de uso duplo. Usando flutuador vai levar a valores arredondados imprevisíveis na maioria das situações

Embora não seja ideal para todas as operações, se você está fazendo telhas mapa ou trabalhar com um grande número de marcadores (pontos) com apenas uma projeção (eg Mercator, como o Google Maps e muitos outros slippy mapeia os quadros de esperar), I ter encontrado o que eu chamo de "Vast Coordinate System" para ser realmente, realmente útil. Basicamente, você armazenar x e coordenadas de pixel y em algum vias zoom-in - Eu uso o nível de zoom 23. Isto tem várias vantagens:

  • Você faz o / lng lat caro para transformação de pixel mercator uma vez, em vez de cada vez que você lidar com o ponto
  • Obtendo a telha de coordenadas de um registro dado um nível de zoom leva um deslocamento para a direita.
  • Obter a coordenada de pixel de um registro leva um deslocamento para a direita e um bit a bit AND.
  • As mudanças são tão leves que é prático para fazê-las em SQL, o que significa que você pode fazer um DISTINCT para retornar apenas um registro por local de pixel, o que irá reduzir os registros de número retornado pela infra-estrutura, o que significa menos processamento na extremidade dianteira.

Eu falei sobre tudo isso em um post recente: http://blog.webfoot.com/2013/03/ 12 / otimizando-map-tile-geração /

Estou muito surpreendido por algumas respostas / comentários.

Por que diabos alguém iria estar disposto a voluntarely "pré-queda" a precisão, e, posteriormente, realizar cálculos sobre os números piores? Sons em última análise, estúpido.

Se a fonte tem precisão de 64-bit, certamente seria mudo para corrigir voluntarely a escala para por exemplo. 6 casas decimais, e limitar a precisão para um máximo de 9 digts significativos (o que acontece com o formato decimal 9,6 comumente proposto).

Naturalmente, um armazena os dados com a precisão que o material de origem tem. A única razão para precisão diminuição seria espaço de armazenamento limitado.

  • figuras fonte loja com precisão originais
  • figuras Loja calculada a partir da fonte na precisão do cálculo acontece (ex. Se as duplas usa código aplicação, armazenar os resultados como duplos)

O 9,6-formato decimal provoca uma phenomen snap-to-grid. Esse deve ser o último passo, se é em tudo acontecer.

Eu não convite erros acumulados ao meu ninho.

As funções espaciais em PostGIS são muito mais funcional (isto é, não constrangido a operações BBOX) do que aqueles nas funções espaciais MySQL. Confira: link de texto

TL; DR

Use FLOAT (8,5), se você não está trabalhando em NASA / militar e não fazendo aeronaves navi sistemas.


Para responder a sua pergunta completamente, você precisa considerar várias coisas:

Formato

  • <> fortes graus minutos segundos : 40 ° 26 '46 "N 79 ° 58' 56" W
  • <> fortes graus decimal minutos : 40 ° 26,767 'N 79 ° 58,933' W
  • decimais graus 1 : 40,446 79,982 ° N ° W
  • decimais graus 2 : -32,60875, 21,27812
  • Algum outro formato home-made? Noone proíbe você de fazer o seu próprio sistema de coordenadas home-centric e armazená-lo como título e distância da sua casa. Isso poderia fazer sentido para alguns problemas específicos que você está trabalhando.

Assim, a primeira parte da resposta seria -. Você pode armazenar as coordenadas no formatar seus usos de aplicação para evitar conversões constantes e para trás e fazer consultas simples SQL

Provavelmente você usa o Google Maps ou OSM para exibir seus dados, e GMaps estão usando "graus decimais 2" formato. Por isso, será mais fácil de coordenadas de lojas no mesmo formato.

Precision

Então, você gostaria de definir a precisão que você precisa. Claro que você pode armazenar coordenadas como "-32.608697550570334,21.278081997935146", mas você já se preocupava milímetros enquanto a navegação para o ponto? Se você não está trabalhando na NASA e não fazendo satélites ou foguetes ou aviões trajetórias, você deve estar bem com vários metros de precisão.

formato comumente usado é 5 dígitos após pontos que lhe dá 50 centímetros precisão.

Exemplo : há uma distância de 1 cm entre X, 21,278081 8 e X, 21,278081 9 . Então 7 dígitos depois do ponto dar-lhe 1/2 centímetro precisão e 5 dígitos depois do ponto lhe dará 1/2 metros de precisão (porque a distância mínima entre pontos distintos é 1m, então erro de arredondamento não pode ter mais do que a metade dela). Para a maioria dos fins civis deve ser suficiente.

graus formato minutos decimais (40 ° 26,767 'N 79 ° 58,933' W) lhe dá exatamente a mesma precisão como 5 dígitos depois do ponto

Espaço-eficiente de armazenamento

Se você selecionou o formato decimal, então o seu coordenada é um par (-32,60875, 21,27812). Obviamente, 2 x (1 bit de sinal, 2 dígitos para graus e 5 dígitos para expoente) será suficiente.

Então aqui eu gostaria de apoio Alix Axel a partir de comentários dizendo que o Google sugestão para armazená-lo em FLOAT (10,6) é realmente extra, porque você não precisa de 4 dígitos para o principal parte (uma vez que o sinal é separado e latitude é limitado a 90 e longitude é limitado a 180). Você pode facilmente usar FLOAT (8,5) durante 1 / precisão 2m ou FLOAT (9,6) para uma precisão de 50/2 centímetros. Ou você ainda pode armazenar lat e longo em tipos separados, porque FLOAT (7,5) é suficiente para lat. Veja MySQL tipos float referência . Qualquer um deles será como FLOAT normal e igual a 4 bytes de qualquer maneira.

Normalmente, o espaço não é um problema hoje em dia, mas se você quiser realmente otimizar o armazenamento, por algum motivo (Disclaimer: não faça pré-optimization), você pode comprimir lat (não mais de 91 000 valores sinal +) + longo (não mais do que 181 000 valores de sinal +) para 21 bits, que é significativamente menor que 2xFLOAT (8 bytes == 64 bits)

  1. latitudes variam de -90 a +90 (graus), de modo DECIMAL (10, 8) é ok para que

  2. longitudes variar de -180 a +180 (graus), então você precisa DECIMAL (11, 8).

Nota:. O primeiro número é o número total de dígitos armazenados, eo segundo é o número depois do ponto decimal

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

cálculos Lat Long exigem precisão, portanto, usar algum tipo de tipo decimal e fazer a precisão de pelo menos 2 maior do que o número que irá armazenar a fim de realizar cálculos matemáticos. Eu não sei sobre os meus tipos de dados SQL, mas no SQL Server as pessoas costumam usar float ou real em vez de decimal e entrar em apuros, porque estes são são estimadas não números reais. Então, basta verificar se o tipo de dados que uso é um verdadeiro tipo decimal e não um tipo de decimal flutuante e você deve ser fino.

A FLOAT deve dar-lhe toda a precisão que você precisa, e ser melhor para funções de comparação de armazenar cada co-ordenada como uma string ou similar.

Se a sua versão do MySQL for anterior a 5.0.3, você pode precisar de tomar cuidado de certos flutuante erros de comparação de ponto no entanto.

Antes do MySQL 5.0.3, colunas decimais armazenar valores com precisão exata, porque eles são representados como strings, mas os cálculos sobre valores decimais são feitas usando operações de ponto flutuante. A partir de 5.0.3, MySQL operações executa decimais com uma precisão de 64 dígitos decimais, o que deve resolver os problemas imprecisão mais comuns quando se trata de colunas decimais

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top