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

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

Ответы [ 20 ]

6 голосов
/ 26 ноября 2015

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

  • если вы полагаетесь на 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.

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

4 голосов
/ 19 декабря 2012

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

4 голосов
/ 23 июля 2010

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

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

4 голосов
/ 03 апреля 2013

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

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

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

4 голосов
/ 26 апреля 2016

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

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

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

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

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

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

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

3 голосов
/ 29 декабря 2008

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

2 голосов
/ 14 августа 2018

TL; DR

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


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

Формат

  • градус минут, секунд : 40 ° 26 ′ 46 ″ с.ш. 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 см.

Пример : расстояние между X, X 21,278081 8 и X, составляет 1 см, 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 бита)

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

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

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

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

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

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

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

A <a href="http://dev.mysql.com/doc/refman/5.1/en/numeric-type-overview.htm" rel="nofollow noreferrer">FLOAT</a> должно дать вам всю необходимую точность и быть лучше для функций сравнения, чем сохранять каждую координату в виде строки или тому подобного.

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

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

...