Какой идеальный тип данных использовать при хранении широты / долготы в базе данных MySQL? - PullRequest
405 голосов
/ 01 октября 2008

Учитывая, что я буду выполнять вычисления для пар широта / длинная, какой тип данных лучше всего подходит для использования с базой данных MySQL?

Ответы [ 20 ]

154 голосов
/ 01 октября 2008
146 голосов
/ 13 мая 2011

Google предоставляет начало, чтобы закончить решение PHP / MySQL для примера приложения «Локатор магазина» с Google Maps. В этом примере они хранят значения lat / lng как «Float» с длиной «10,6»

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

114 голосов
/ 04 августа 2014

В основном это зависит от точности, которая вам нужна для вашего местоположения. Используя DOUBLE, вы получите точность 3,5 нм. DECIMAL (8,6) / (9,6) опускается до 16см. Плавание составляет 1,7 м ...

У этой очень интересной таблицы есть более полный список: 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

Надеюсь, это поможет.

74 голосов
/ 02 октября 2008

Пространственные расширения MySQL - лучший вариант, потому что у вас есть полный список пространственных операторов и индексов. Пространственный индекс позволит вам очень быстро выполнять расчеты на основе расстояния. Пожалуйста, имейте в виду, что по состоянию на 6.0 Пространственное расширение все еще не завершено. Я не опускаю MySQL Spatial, а лишь сообщаю вам о подводных камнях, прежде чем вы слишком далеко продвинетесь в этом.

Если вы имеете дело только с точками и только с функцией DISTANCE, это нормально. Если вам необходимо выполнить какие-либо расчеты с полигонами, линиями или буферизованными точками, пространственные операторы не дают точных результатов, если вы не используете оператор «связать». См. Предупреждение вверху 21.5.6 . Отношения, такие как содержит, внутри или пересекаются, используют MBR, а не точную геометрическую форму (то есть эллипс рассматривается как прямоугольник).

Кроме того, расстояния в MySQL Spatial указаны в тех же единицах, что и ваша первая геометрия. Это означает, что если вы используете десятичные градусы, то ваши измерения расстояния в десятичных градусах. Это очень затруднит получение точных результатов, поскольку вы получаете фуртур от экватора.

70 голосов
/ 01 октября 2008

Когда я сделал это для навигационной базы данных, построенной из ARINC424, я провел немало испытаний и, оглядываясь на код, использовал DECIMAL (18,12) (на самом деле NUMERIC (18,12), потому что это был firebird ).

Плавающие и двойные числа не так точны и могут привести к ошибкам округления, что может быть очень плохо. Я не могу вспомнить, нашел ли я какие-либо реальные данные, у которых были проблемы, - но я вполне уверен, что невозможность точного хранения в плавающей или двойной переменной может вызвать проблемы

Дело в том, что при использовании градусов или радиан мы знаем диапазон значений - а дробная часть нуждается в наибольшем количестве цифр.

Пространственные расширения MySQL являются хорошей альтернативой, поскольку они следуют Модель геометрии OpenGIS . Я не использовал их, потому что мне нужно было сохранять базу данных переносимой.

37 голосов
/ 15 июня 2015

Зависит от требуемой точности.

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

От: http://mysql.rjweb.org/doc.php/latlng

Подведем итог:

  • Самый точный доступный вариант - DOUBLE.
  • Наиболее распространенный вид: DECIMAL(8,6)/(9,6).

Начиная с MySQL 5.7 , рассмотрите возможность использования Пространственные типы данных (SDT), в частности POINT для хранения одной координаты. До версии 5.7 SDT не поддерживает индексы (за исключением 5.6, когда тип таблицы - MyISAM).

Примечание:

32 голосов
/ 28 сентября 2013

Основано на этой статье вики http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy соответствующий тип данных в MySQL является десятичным (9,6) для хранения долготы и широты в отдельные поля.

19 голосов
/ 13 января 2015

Используйте DECIMAL(8,6) для широты (от 90 до -90 градусов) и DECIMAL(9,6) для долготы (от 180 до -180 градусов). 6 знаков после запятой хорошо для большинства приложений. Оба должны быть "подписаны", чтобы учесть отрицательные значения.

13 голосов
/ 22 июля 2016

Не нужно далеко ходить, по данным Google Maps, лучше всего FLOAT (10,6) для широты и долготы.

7 голосов
/ 19 октября 2008

Мы храним широту / долготу X 1 000 000 в нашей базе данных Oracle как NUMBERS, чтобы избежать ошибок округления с двойными числами.

Учитывая, что широта / долгота с точностью до шестого знака после запятой составляет 10 см, это все, что нам нужно. Многие другие базы данных также хранят широту / долготу до 6-го знака после запятой.

...