Quel est le type de données idéal à utiliser pour stocker la latitude / longitude dans une base de données MySQL?

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

Question

Sachant que je vais effectuer des calculs sur des paires lat / long, quel type de données est le mieux adapté à une utilisation avec une base de données MySQL?

Était-ce utile?

La solution

Utilisez les extensions spatiales de MySQL avec MySQL

. / p>

Autres conseils

Google fournit un exemple complet de solution PHP / MySQL "Store Locator". application avec Google Maps. Dans cet exemple, ils stockent les valeurs lat / lng sous le nom "Float". avec une longueur de "10,6"

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

Cela dépend essentiellement de la précision dont vous avez besoin pour vos emplacements. En utilisant DOUBLE, vous aurez une précision de 3,5 nm. DECIMAL (8,6) / (9,6) descend à 16cm. FLOAT is 1.7m ...

Ce tableau très intéressant a une liste plus complète: 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

J'espère que cela vous aidera.

Les extensions spatiales de MySQL sont la meilleure option car vous disposez de la liste complète des opérateurs spatiaux et des index. Un index spatial vous permettra d'effectuer très rapidement des calculs basés sur la distance. N'oubliez pas qu'à partir de la version 6.0, l'extension spatiale est toujours incomplète. Je ne dénigre pas MySQL Spatial, je vous tiens au courant des pièges avant d’aller trop loin dans ce domaine.

Si vous utilisez uniquement des points et que la fonction DISTANCE, tout va bien. Si vous devez effectuer des calculs avec des polygones, des lignes ou des points tamponnés, les opérateurs spatiaux ne fournissent pas les résultats exacts à moins que vous n'utilisiez le paramètre "relier". opérateur. Voir l'avertissement au sommet de 21.5.6 . Les relations telles que contient, dans, ou intersections utilisent le MBR, et non la forme géométrique exacte (c’est-à-dire qu'une Ellipse est traitée comme un rectangle).

De plus, les distances dans MySQL Spatial sont dans les mêmes unités que votre première géométrie. Cela signifie que si vous utilisez des degrés décimaux, vos mesures de distance sont exprimées en degrés décimaux. Cela rendra très difficile l'obtention de résultats exacts à mesure que vous obtiendrez de l'équateur.

Lorsque j’ai fait cela pour une base de données de navigation construite à partir d’ARINC424, j’ai fait pas mal de tests et j’ai regardé dans le code, j’ai utilisé un DECIMAL (18,12) (en fait un NUMERIC (18,12) parce que c’était Firebird. ).

Les flottants et les doubles ne sont pas aussi précis et peuvent entraîner des erreurs d'arrondi, ce qui peut être une très mauvaise chose. Je ne me souviens pas si j'ai trouvé des données réelles qui posaient problème, mais je suis à peu près certain que l'incapacité de stocker avec précision dans un flottant ou un double pourrait causer des problèmes

Le fait est que, lorsque vous utilisez des degrés ou des radians, nous connaissons la plage des valeurs - et la partie décimale nécessite le plus grand nombre de chiffres.

Les extensions MySQL Spatial sont une bonne alternative. car ils suivent le modèle de géométrie OpenGIS . Je ne les ai pas utilisées car je devais garder ma base de données portable.

Dépend de la précision requise.

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

Pour résumer:

  • L'option disponible la plus précise est DOUBLE .
  • Le type de vus le plus utilisé est DECIMAL (8,6) / (9,6) .

À partir de MySQL 5.7 , envisagez d'utiliser Spatial Data Types (SDT), plus précisément POINT pour stocker une seule coordonnée. Avant la version 5.7, SDT ne prend pas en charge les index (à l’exception de 5.6 lorsque le type de table est MyISAM).

Remarque:

  • Lorsque vous utilisez la classe POINT , l'ordre des arguments pour le stockage des coordonnées doit être POINT (latitude, longitude) .
  • Il existe une syntaxe spéciale pour la création d'un index spatial .
  • Le principal avantage de l'utilisation de la technologie SDT est que vous avez accès aux fonctions d'analyse spatiale. , par exemple calcul de la distance entre deux points ( ST_Distance ) et déterminer si un point est contenu dans une autre zone ( ST_Contains ).

Basé sur cet article du wiki http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy le type de données approprié dans MySQL est Decimal (9,6) pour stocker la longitude et la latitude dans champs séparés.

Utilisez DECIMAL (8,6) pour la latitude (90 à -90 degrés) et DECIMAL (9,6) pour la longitude (180 à -180 degrés). 6 décimales conviennent à la plupart des applications. Les deux doivent être " signés " pour permettre des valeurs négatives.

Inutile d’aller loin, selon Google Maps, le meilleur est FLOAT (10,6) pour les lat et lng.

Nous stockons latitude / longitude X 1 000 000 dans notre base de données Oracle sous le nom NUMBERS pour éviter les erreurs d'arrondi par des doubles.

Étant donné que la latitude / longitude à la 6ème décimale était de 10 cm, la précision était tout ce dont nous avions besoin. De nombreuses autres bases de données stockent également la latitude / longitude jusqu'à la 6ème décimale.

Dans une perspective complètement différente et plus simple:

De cette façon, vous n'avez pas à vous soucier de l'indexation des numéros ni de tous les autres problèmes associés aux types de données qui risquent de corrompre vos coordonnées.

en fonction de votre application, je suggère d'utiliser FLOAT (9,6)

Les clés spatiales vous donneront plus de fonctionnalités, mais dans les tests de production, les flottants sont beaucoup plus rapides que les clés spatiales. (0,01 VS 0,001 en AVG)

MySQL utilise le double pour tous les flottants ... Alors utilisez le type double. L'utilisation de float conduira à des valeurs arrondies imprévisibles dans la plupart des situations

Bien que cela ne soit pas optimal pour toutes les opérations, si vous créez des tuiles de carte ou travaillez avec un grand nombre de marqueurs (points) avec une seule projection (par exemple, Mercator, comme Google Maps et de nombreux autres frameworks de cartes glissantes attendus), je J'ai trouvé ce que j'appelle "Vaste système de coordonnées". être vraiment très pratique. Fondamentalement, vous stockez les coordonnées x et y du pixel à un certain niveau - j'utilise le niveau de zoom 23. Cela présente plusieurs avantages:

  • Vous effectuez la transformation coûteuse lat / lng en pixels de mercator une fois au lieu de chaque fois que vous manipulez le point
  • Obtenir la coordonnée de la tuile à partir d'un enregistrement en fonction d'un niveau de zoom prend un décalage à droite.
  • Obtenir la coordonnée en pixels d'un enregistrement prend un décalage à droite et un ET au niveau du bit.
  • Les changements sont si légers qu'il est pratique de les utiliser en SQL, ce qui signifie que vous pouvez effectuer une commande DISTINCT pour renvoyer un seul enregistrement par emplacement de pixel, ce qui réduira le nombre d'enregistrements renvoyés par le serveur principal, ce qui signifie moins traitement sur le front-end.

J'ai parlé de tout cela dans un récent article de blog:     http://blog.webfoot.com/2013/03/ 12 / génération-tuile-carte-optimisation /

Je suis très surpris par certaines réponses / commentaires.

Pourquoi diable quelqu'un voudrait-il volontairement "pré-diminuer" la précision, et ensuite effectuer des calculs sur les pires nombres? Cela semble finalement stupide.

Si la source a une précision de 64 bits, il serait certainement idiot de fixer volontairement l'échelle à, par exemple. 6 décimales et limitez la précision à un maximum de 9 chiffres significatifs (ce qui se produit avec le format décimal 9.6 couramment proposé).

Naturellement, les données sont stockées avec la précision du matériau source. La seule raison de diminuer la précision serait un espace de stockage limité.

  • Stocker les figures source avec une précision originale
  • Stockez les chiffres calculés à partir de la source dans la précision du calcul (par exemple, si le code d’application utilise des doubles, stockez les résultats sous forme de doubles)

Le format décimal 9.6 provoque un phénomène d’accrochage à la grille. Cela devrait être la toute dernière étape, si cela doit se produire.

Je n'inviterais pas les erreurs accumulées dans mon nid.

Les fonctions spatiales dans PostGIS sont beaucoup plus fonctionnelles (c'est-à-dire non limitées aux opérations BBOX) que celles des fonctions spatiales MySQL. Découvrez-le: texte du lien

TL; DR

Utilisez FLOAT (8,5) si vous ne travaillez pas dans la NASA / militaire et ne fabriquez pas de systèmes de navigation aérienne.

Pour répondre pleinement à votre question, vous devez prendre en compte plusieurs éléments:

Format

  • degrés minutes secondes : 40 & # 176; 26 & # 8242; 46 & # 8243; N 79 & # 176; 58 & # 8242; 56 & # 8243; W
  • en degrés décimaux minutes : 40 & # 176; 26,767 & # 8242; N 79 & # 176; 58,933 & # 8242; W
  • degrés décimaux 1 : 40,446 & # 176; N 79,982 & # 176; W
  • degrés décimaux 2 : -32,60875, 21,27812
  • Un autre format fait maison? Personne ne vous interdit de créer votre propre système de coordonnées centré sur votre maison et de le stocker comme cap et à distance de votre domicile. Cela peut avoir un sens pour certains problèmes spécifiques sur lesquels vous travaillez.

La première partie de la réponse serait donc: vous pouvez stocker les coordonnées dans le format utilisé par votre application pour éviter les conversions constantes dans les deux sens et simplifier les requêtes SQL.

Il est fort probable que vous utilisiez Google Maps ou OSM pour afficher vos données, et les cartes GMaps utilisent des "degrés décimaux 2". format. Il sera donc plus facile de stocker les coordonnées dans le même format.

Précision

Ensuite, vous souhaitez définir la précision dont vous avez besoin. Bien sûr, vous pouvez stocker des coordonnées telles que "-32.608697550570334,21.278081997935146", mais vous êtes-vous déjà soucié des millimètres lorsque vous naviguez jusqu'au point? Si vous ne travaillez pas dans la NASA et ne faites pas de trajectoires de satellites, de fusées ou d’avions, vous devriez vous en sortir avec une précision de plusieurs mètres.

Le format couramment utilisé est 5 chiffres après les points, ce qui vous donne une précision de 50 cm.

Exemple : une distance de 1 cm sépare X 21.278081 8 de X 21.278081 9 . Ainsi, 7 chiffres après le point vous donnent une précision de 1 / 2cm et 5 chiffres après le point vous donneront une précision de 1/2 mètre (parce que la distance minimale entre des points distincts est de 1 m, une erreur d'arrondi ne peut donc pas en dépasser la moitié). Pour la plupart des objectifs civils, cela devrait suffire.

Le format

minute décimal (40 & # 176; 26,767 & # 8242; N 79 & # 176; 58,933 & # 8242; W) vous donne exactement la même précision que 5 chiffres après le point

Stockage peu encombrant

Si vous avez sélectionné le format décimal, votre coordonnée est une paire (-32.60875, 21.27812). Évidemment, 2 x (1 bit pour le signe, 2 chiffres pour les degrés et 5 chiffres pour l'exposant) suffiront.

C’est pourquoi, ici, je voudrais soutenir Alix Axel dans les commentaires disant que la suggestion de Google de le stocker dans FLOAT (10,6) est vraiment extra, car vous n'avez pas besoin de 4 chiffres pour le texte principal. partie (puisque le signe est séparé et que la latitude est limitée à 90 et la longitude est limitée à 180). Vous pouvez facilement utiliser FLOAT (8,5) pour une précision de 1 / 2m ou FLOAT (9,6) pour une précision de 50/2cm. Ou vous pouvez même stocker lat et long dans des types séparés, parce que FLOAT (7,5) est suffisant pour lat. Voir les types flottants de MySQL référence . N'importe lequel d'entre eux ressemblera à FLOAT normal et sera égal à 4 octets.

Habituellement, l'espace n'est plus un problème aujourd'hui, mais si vous souhaitez vraiment optimiser le stockage pour une raison quelconque (Avertissement: ne faites pas de pré-optimisation), vous pouvez compresser lat (pas plus de 91 000 valeurs + signe) + long (pas plus de 181 000 valeurs + signe) à 21 bits, ce qui est nettement inférieur à 2xFLOAT (8 octets == 64 bits)

  1. Les latitudes varient de -90 à +90 (degrés), donc DECIMAL (10, 8) est acceptable pour cela

  2. les longitudes vont de -180 à +180 (degrés), vous avez donc besoin de DECIMAL (11, 8).

Remarque: le premier nombre correspond au nombre total de chiffres stockés et le second au nombre situé après le point décimal.

En bref: lat DECIMAL (10, 8) NON NUL, lng DECIMAL (11, 8) NON NULL

Les calculs Lat Long exigent de la précision, utilisez donc un type de type décimal et augmentez la précision d'au moins 2 fois par rapport au nombre que vous enregistrez pour effectuer des calculs mathématiques. Je ne connais pas les types de données de mon SQL, mais dans SQL Server, les gens utilisent souvent float ou real au lieu de décimal et ont des problèmes parce que ce sont des nombres estimés qui ne sont pas réels. Assurez-vous simplement que le type de données que vous utilisez est un type décimal réel et non un type décimal flottant et tout devrait bien se passer.

Un FLOAT devrait vous donner toute la précision dont vous avez besoin et être meilleur pour les fonctions de comparaison que de stocker chaque coordonnée sous forme de chaîne ou similaire.

Si votre version de MySQL est antérieure à la version 5.0.3, vous devrez peut-être tenir compte de certains Erreurs de comparaison en virgule flottante cependant.

  

Avant MySQL 5.0.3, les colonnes DECIMAL stockaient les valeurs avec une précision exacte car elles étaient représentées sous forme de chaînes, mais les calculs sur les valeurs DECIMAL sont effectués à l'aide d'opérations à virgule flottante. Depuis la version 5.0.3, MySQL effectue les opérations DECIMAL avec une précision de 64 décimales, ce qui devrait résoudre les problèmes d’inexactitude les plus courants en ce qui concerne les colonnes DECIMAL

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top