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

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

Ответ 2

Google предоставляет начало для завершения PHP/MySQL-решения для примера приложения "Store Locator" с Google Maps. В этом примере они сохраняют значения lat/lng как "Float" с длиной "10,6"

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

Ответ 3

В основном это зависит от точности, необходимой для ваших местоположений. Используя DOUBLE, вы получите точность 3,5 нм. DECIMAL (8,6)/(9,6) сокращается до 16 см. FLOAT составляет 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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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).

Примечание:

Ответ 7

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

В совершенно другой и более простой перспективе:

  • если вы полагаетесь на Google, чтобы показывать свои карты, маркеры, полигоны, что угодно, а затем разрешить вычисления Google!
  • вы сохраняете ресурсы на своем сервере, и вы просто сохраняете широту и долготу вместе как одну строку (VARCHAR), например: " - 0000.0000001, -0000.000000000000001" (длина 35 и если число имеет более 7 десятичных цифр, то округляется);
  • Если Google вернет более 7 десятичных цифр на номер, вы можете получить эти данные, хранящиеся в вашей строке, на всякий случай, если вы хотите обнаружить некоторые бегства или микробы в будущем;
  • вы можете использовать их расстояние матрицы или их геометрия для вычисления расстояний или определение точек в определенных областях с такими же простыми вызовами: google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • существует множество "серверных" API, которые вы можете использовать (в Python, Ruby on Rails, PHP, CodeIgniter, Laravel, Yii, Zend Framework и т.д.), которые используют API Карт Google.

Таким образом вам не нужно беспокоиться об индексах и всех других проблемах, связанных с типами данных, которые могут испортить ваши координаты.

Ответ 12

в зависимости от вашего приложения, я предлагаю использовать FLOAT (9,6)

пространственные ключи предоставят вам больше возможностей, но по производственным эталонам поплавки намного быстрее, чем пространственные ключи. (0,01 VS 0,001 в AVG)

Ответ 13

Пока он не является оптимальным для всех операций, если вы делаете картографические плитки или работаете с большим количеством маркеров (точек) только с одной проекцией (например, Mercator, например, Карты Google и многие другие слабые карты), я нашли то, что я называю "Vast Coordinate System", действительно, очень удобно. В основном, вы сохраняете координаты x и y пикселя каким-то образом - увеличенным - я использую уровень масштабирования 23. Это имеет несколько преимуществ:

  • Вы делаете дорогостоящие преобразования lat/lng в пиксель пикселя меркатора один раз, а не каждый раз, когда вы обрабатываете точку
  • Получение координаты плитки из записи с учетом уровня масштабирования занимает один сдвиг вправо.
  • Получение координаты пикселя из записи занимает один правый сдвиг и побитовое значение AND.
  • Сдвиги настолько легки, что их можно делать в SQL, что означает, что вы можете сделать DISTINCT, чтобы вернуть только одну запись на пиксель, которая сократит количество записей, возвращаемых бэкэнд, что означает меньше обработка на переднем конце.

Я рассказывал обо всем этом в недавнем сообщении в блоге:  http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/

Ответ 14

Пространственные функции в PostGIS гораздо более функциональны (т.е. не ограничены операциями BBOX), чем функции пространственных функций MySQL. Проверьте это: текст ссылки

Ответ 15

MySQL использует double для всех поплавков... Поэтому используйте тип double. Использование float приведет к непредсказуемым округленным значениям в большинстве ситуаций.

Ответ 16

Я очень удивлен некоторыми ответами/комментариями.

Почему бы вам не захотеть добровольно "преуменьшить" точность, а затем выполнить вычисления по худшим цифрам? Звучит глупо.

Если источник имеет 64-битную точность, то, конечно, было бы немым, чтобы вовремя исправить масштаб, например. 6 десятичных знаков и ограничить точность до 9 значащих цифр (что происходит с обычно предлагаемым десятичным форматом 9.6).

Естественно, что один хранит данные с точностью, которую имеет исходный материал. Единственной причиной снижения точности было бы ограниченное пространство для хранения.

  • Сохранить исходные данные с оригинальной точностью
  • Сохранять цифры, рассчитываемые из источника, в точности, которую выполняет расчет (например, если код приложения использует удвоение, сохраняйте результаты как удвоенные)

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

Я не приглашал бы накопленные ошибки в свое гнездо.

Ответ 17

TL; DR

Используйте FLOAT (8,5), если вы не работаете в НАСА/военных и не создаете навигационные системы самолетов.


Чтобы полностью ответить на ваш вопрос, вам нужно рассмотреть несколько вещей:

Формат

  • градусы минут секунд: 40 ° 26 '46 "N 79 ° 58' 56" Вт
  • градусы десятичных минут: 40 ° 26,767 'N 79 ° 58,933' W
  • десятичные степени 1: 40,446 ° N 79,982 ° W
  • десятичные степени 2: -32.60875, 21.27812
  • Какой-то другой домашний формат? Никто не запрещает вам создавать свою домашнюю систему координат и хранить ее как заголовок и расстояние от вашего дома. Это может иметь смысл для некоторых конкретных проблем, над которыми вы работаете.

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

Скорее всего, вы используете Google Maps или OSM для отображения своих данных, а GMaps используют формат "десятичной степени 2". Поэтому сохранять координаты в том же формате проще.

точность

Затем вы хотите определить нужную точность. Конечно, вы можете хранить координаты, такие как "-32.608697550570334,21.278081997935146", но вы когда-нибудь заботились о миллиметрах при навигации к точке? Если вы не работаете в НАСА и не выполняете траектории спутников или ракет или самолетов, вы должны быть в порядке с точностью до нескольких метров.

Обычно используемый формат составляет 5 цифр после точек, что дает вам точность 50 см.

Пример: расстояние 1 см между X, 21.278081 8 и X, 21.278081 9. Таким образом, 7 цифр после точки дают вам точность 1/2 см и 5 цифр после точки дают вам точность в 1/2 метра (поскольку минимальное расстояние между различными точками равно 1 м, поэтому ошибка округления не может превышать половины). Для большинства гражданских целей этого должно быть достаточно.

градус десятичных минут (40 ° 26,767 'N 79 ° 58,933' W) дает вам точно такую же точность, как 5 цифр после точки

Экономичное пространство

Если вы выбрали десятичный формат, то ваша координата - это пара (-32.60875, 21.27812). Очевидно, достаточно 2 x (1 бит для знака, 2 цифры для степеней и 5 цифр для экспоненты).

Поэтому я хотел бы поддержать Alix Axel от комментариев, говорящих, что предложение Google хранить его в FLOAT (10,6) действительно является дополнительным, потому что вам не нужны 4 цифры для основной части (поскольку знак разделен и широта ограничена до 90 и долгота ограничивается 180). Вы можете легко использовать FLOAT (8,5) для точности 1/2 м или FLOAT (9,6) для точности 50/2 см. Или вы даже можете хранить lat и long в разделенных типах, потому что FLOAT (7,5) достаточно для lat. См. Ссылку на типы ссылок на MySQL. Любой из них будет как обычный FLOAT и равен 4 байтам в любом случае.

Обычно пространство не является проблемой в настоящее время, но если вы хотите по-настоящему оптимизировать хранилище по какой-либо причине (Отказ от ответственности: не делайте предварительной оптимизации), вы можете сжать lat (не более 91 000 значений + знак) + long (нет более 181 000 значений + знак) до 21 бит, что значительно меньше 2xFLOAT (8 байтов == 64 бит)

Ответ 18

  1. Широты варьируются от -90 до +90 (градусы), поэтому DECIMAL (10, 8) подходит для этого

  2. долготы варьируются от -180 до +180 (градусы), поэтому вам нужно DECIMAL (11, 8).

Примечание. Первое число - это общее количество сохраненных цифр, а второе - число после десятичной точки.

Короче: lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL

Ответ 19

Расчеты Lat Long требуют точности, поэтому используйте тип десятичного типа и сделайте точность не менее чем на 2 выше, чем число, которое вы будете хранить для выполнения математических вычислений. Я не знаю о моих типах данных sql, но в SQL-сервере люди часто используют float или real вместо десятичного числа и попадают в неприятности, потому что это оценочные числа, которые не являются реальными. Поэтому просто убедитесь, что тип данных, который вы используете, является истинным десятичным типом, а не плавающим десятичным типом, и вы должны быть в порядке.

Ответ 20

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

Если ваша версия MySQL более ранняя, чем 5.0.3, вам, возможно, придется учитывать некоторые ошибки сравнения с плавающей запятой.

До MySQL 5.0.3 столбцы DECIMAL хранят значения с точной точностью, потому что они представлены в виде строк, но вычисления значений DECIMAL выполняются с использованием операций с плавающей запятой. Начиная с версии 5.0.3 MySQL выполняет операции DECIMAL с точностью до 64 десятичных цифр, что должно решить наиболее распространенные проблемы неточности, когда дело доходит до столбцов DECIMAL.