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


432

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


1
Я нашел эту ссылку очень полезной: howto-use-mysql-spatial-ext.blogspot.com/2007/11/… Возможно, она немного старше, но содержит полное объяснение, включая примеры.
Madc

Имхо большинство людей здесь не понимают, что происходит. Как только код приложения касается числа, при условии, что каждый использует двойные числа (что большинство делает), число превращается в максимально двойную точность . Хранение его с миллионом знаков после запятой не принесет пользы. Хранение его с ограниченным количеством десятичных знаков (например, 6) разрушает часть этой точности и добавляет накопленную ошибку каждый раз, когда она перезаписывается в базу данных . Двойное число содержит около 16 значащих чисел, возможно, все десятичные дроби. Удаление 10 из них создает накопленную ошибку с течением времени. Это «плавающая точка» по причине. Прод.
Штормград

Продолжение: 6 знаков после запятой могут быть в порядке при сохранении фигуры, полученной из внешнего источника, без изменений и впервые - в качестве исходного материала. Но если выполнить вычисление для него хотя бы один раз и сохранить его снова, будет глупо удалить часть его точности, применяя определенный десятичный формат. Выполнение вычислений только внутри сервера может отличаться (сервер может использовать или не использовать что-то другое, кроме удваивающихся внутренних значений), и использование худших числовых представлений, чем double, в вычислениях приложения c уменьшает в равной степени потребность в точности хранения.
Штормград

Продолжение: ЕСЛИ сервер хранит число с более высокой точностью, несмотря на заявленное «9,6» (что я не знаю, так ли это), то все это не имеет значения, а формат - просто вопрос удобства - мало что дает делать с вопросами точности. Но я не удивлюсь, если сервер на самом деле округляет любое число до 6 десятичной точности с этим форматом.
Штормград

Cont: Наконец: Для широта, долгота - х, 6 - десятичное это вопрос щелкать в ок 11-сантиметровая сетка. Каждый раз, когда кто-то читает (касается), рассчитывает и сохраняет снова, с шестью десятичными знаками, будет новый щелчок (= накопленная ошибка). Если все ошибки будут идти в одном направлении, будет большая ошибка. Если выполнить временные умножения на нем (например, увеличить, затем вычесть и уменьшить), оно может увеличиться еще больше. Не отказывайтесь от точности без хорошего рассона!
Штормград

Ответы:


161

Используйте пространственные расширения MySQL вместе с ГИС.


25
Есть ли у вас какие-либо другие ссылки на примеры или какую-либо другую информацию о том, как лучше всего начать с ними?
Codebeef

6
MYSQL Spatial является хорошим вариантом, но все еще имеет значительные ограничения и предостережения (по состоянию на 6). Пожалуйста, смотрите мой ответ ниже ...
Джеймс Шек

1
@ Джеймс Шек прав. Кроме того, MySQL выполняет все свои вычисления с использованием евклидовой геометрии, поэтому он не представляет собой реальный вариант использования lat / lng.
mkuech

FYI; Mysql поддерживает пространственный индекс только с таблицами * .myisam, то есть с механизмом ISAM. Ссылка: dev.mysql.com/doc/refman/5.0/en/creating-spatial-indexes.html
PodTech.io

Посмотрите на эту статью в конце Обновление: mysqlserverteam.com/mysql-5-7-and-gis-an-example
Сингх

150

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

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


11
Google явно не понимает, как работает спецификация FLOAT: FLOAT(10,6)оставляет 4 цифры для целочисленной части координаты. И нет, знак не считается - это происходит из (не) подписанного атрибута.
Аликс Аксель

2
Но если вам нужно сохранить как целые части значения из [0, 180], то их должно быть более чем достаточно, верно?
Hrvoje Golcic

37
@AlixAxel Я думаю, что Google знает, что он делает. Потому что он гласит: « С текущими возможностями масштабирования Google Maps вам нужно только 6 цифр точности после десятичной дроби. Это позволит полям хранить 6 цифр после десятичной запятой, плюс до 4 цифр перед десятичной запятой, например - 123,456789 градусов. " Если флажок без знака установлен, шаблон будет 1234,567890 . Так что никаких проблем.
1.44mb

16
@AlixAxel Он отсчитывает числа в последовательности; не используя фактическую координату ...
Эндрю Эллис

8
Использование типа данных Doubleдля Laravel
FooBar

134

В основном это зависит от точности, которая вам нужна для вашего местоположения. Используя 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

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


2
Мне нужно написать конструктивный, подробный комментарий, сосредоточенный на содержании постов, поэтому я скажу, что, наблюдая таблицу точности, предоставленную на сайте Рика Джеймса, я был слегка удивлен описанием резолюции «блохи на собаке» и чувствовал, что это достойно похвалы. Технически говоря, это было полезное описание, которое помогло мне решить, какой тип данных использовать при сохранении координат для измерения расстояния между двумя адресами, и, @Simon, я хотел бы поблагодарить вас за обмен.
Sam_Butler

Кстати, использование этой ссылки «SMALLINT scaled» ужасно неэффективно. Ответ Огужана - это отличный способ хранить long / lat с 7 цифрами после десятичной точки в 4-байтовом знаке int. Большая точность (~ 1 см) в небольшом размере (4B).
ToolmakerSteve

74

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

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

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


26
Повторение: MySQL Spatial Extensions не подходит для расчета расстояний большого круга между точками на поверхности земли, представленными широтой / долготой. Их функции расстояния и т. Д. Полезны только для декартовых, плоских координат.
О. Джонс

71

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

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

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

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


3
Спасибо, это было полезно. Чувствует себя странно, читая все эти вопросы и ответы с 2008 года, понимая, что это было уже 8 лет назад.
aexl

1
@TheSexiestManinJamaica - До IEEE 754-1985 компьютерное оборудование с плавающей точкой было хаотичным. Был даже на машине, где a*bне было равных b*a(для некоторых значений). Было много примеров несколько , как: 2+2 = 3.9999. Стандарт устранил много беспорядка и был «быстро» принят практически каждым оборудованием и программным обеспечением. Таким образом, эта дискуссия действительна не только с 2008 года, но уже треть века.
Рик Джеймс

42

Зависит от точности, которая вам требуется.

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

Замечания:

  • При использовании POINTкласса порядок аргументов для хранения координат должен быть следующим POINT(latitude, longitude).
  • Существует специальный синтаксис для создания пространственного индекса .
  • Самым большим преимуществом использования SDT является то, что у вас есть доступ к функциям пространственного анализа , например, для расчета расстояния между двумя точками ( ST_Distance) и определения, содержится ли одна точка в другой области ( ST_Contains).

2
Вы копируете вставленную часть предыдущего ответа и «обобщаете» что-то, что парень, который создал эту таблицу , не рекомендовал : «Как РАЗДЕЛИТЬ? Ну, MySQL очень требователен. Так что FLOAT / DOUBLE отсутствуют. DECIMAL отсутствует. Итак, мы застряли в некотором клудже. По сути, нам нужно конвертировать Lat / Lng в некоторый размер INT и использовать PARTITION BY RANGE. » И «FLOAT имеет 24 значащих бита; У DOUBLE 53. (Они не работают с PARTITIONing, но включены для полноты. Часто люди используют DOUBLE, даже не осознавая, насколько это излишний объем и сколько места занимает.) »Просто оставьте часть SDT, которую вы написали.
Armfoot

1
@Armfoot Если вы посмотрите на момент внесения изменений, это другой ответ, который скопирован с меня. Не то, чтобы это имело значение: я вижу переполнение стека больше «заметками для будущего меня».
Gajus

1
Нет, он не копировал у вас, он просто вставил таблицу, как вы сделали по ссылке, на которую он ссылался в 2014 году (ваш пост за 2015 год). Кстати, я думаю, что вы неправильно написали «Special», когда связывали типы пространственных данных. Эта часть, которую вы написали, на самом деле полезна для людей, которые хотят начать их использовать, если вы добавите еще несколько примеров CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;и предупреждение об ограничениях SDT, как упоминал Джеймс , возможно, ваш ответ будет более кратким и точным, чтобы помочь другим людям. ..
Armfoot

@Gajus - Для меня большая честь, что двое из вас нашли мой документ! (Нет, я не знаю, насколько большая блоха, но я чувствовал, что это привлечет чье-то внимание.)
Рик Джеймс

При использовании класса POINT порядок аргументов для хранения координат должен быть POINT (долгота / X, широта / Y).
AndreyP


19

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


DECIMALТип предназначен для финансовых расчетов, где не floor/ceilпринято. Равнина FLOATзначительно превосходит DECIMAL.
Кондыбас

1
@Kondybas - Поскольку основная стоимость в базе данных - выборка строк, разница в производительности между числами с плавающей запятой и десятичными не должна быть проблемой.
Рик Джеймс

14

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


откуда вы взяли эту информацию я не могу ее найти? на случай, если что-то изменится.
webfacer

1
@webfacer, это в разделе «Создание таблицы в MySQL» здесь: developers.google.com/maps/documentation/javascript/… например, lat FLOAT( 10, 6 ) NOT NULL, lng FLOAT( 10, 6 ) NOT NULL
turrican_34

1
@webfacer, похоже, что FLOATсинтаксис устарел с mysql 8.0.17. Mysql теперь рекомендует просто использовать FLOATбез каких-либо прецизионных параметров dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html и dev.mysql.com/doc/refman/5.5/en/floating-point- types.html
turrican_34

7

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

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


2
Умножение на какое-то большое число (например, на миллион) прекрасно, если у вас много данных, потому что целочисленные операции (например, индексированный поиск) выполняются намного быстрее, чем операции с плавающей запятой.
Кейтлин Дак Шервуд

@KaitlinDuckSherwood - биты - биты - я не знаю ни одной причины, по которой 32-разрядное число с плавающей запятой будет медленнее для извлечения (индексированного или иного), чем 32-разрядное целое число. Даже плавающая математика в наши дни достаточно быстра, чтобы не быть проблемой. Тем не менее, я согласен с комментарием использовать подразумеваемый множитель с целым числом: он максимизирует точность, которую вы получаете из 32 бит. Немного перспективных, так как технологии совершенствуются.
ToolmakerSteve

6

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

  • если вы полагаетесь на 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
@ Yarin Это популярный вопрос, когда нескольким (или многим) людям просто нужен ответ о том, как хранить координаты в соответствии со своими потребностями (многие из них могут просто использовать карты Google). Ваш отрицательный голос предполагает, что этот ответ может не помочь им ... Храня координаты в строке, они будут точно знать исходные значения, которые были им предоставлены (например, Google), что поможет им позже, если они решат развить свои Собственное приложение и выполнять на них расчеты. В то время у них все еще будут исходные необработанные данные только потому, что они не перепутали их с конверсиями.
Армфут

4

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

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


1
Можете ли вы предоставить результаты теста с подробностями здесь?
NameNotFoundException

4

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


1
MySQL выполняет операции вDOUBLE . MySQL позволяет хранить данные как 4-байтовые FLOATили 8-байтовые DOUBLE. Таким образом, при сохранении выражения в FLOATстолбце может произойти потеря точности .
Рик Джеймс

4

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

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

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


4

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

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

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

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

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

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

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


2
Потому что большинство инструментов и приложений GPS с точностью до 6 знаков после запятой. Бессмысленно хранить данные с большей точностью, чем то, что могут измерить инструменты gis.stackexchange.com/questions/8650/…
Ярин

1
@ Ярин Да, действительно, но вы говорите об измерениях и GPS, которые не упомянуты в вопросе. Скорее всего, существуют более точные цифры. Но давайте рассмотрим GPS; скажем, исходный набор данных с 64-битными числами с плавающей точкой, который уже содержит неточность. 6 десятичных знаков означает привязку широты к ближайшим приблизительно 11 сантиметрам. Следовательно, теперь, сохраняя только данные (с 6 десятичными знаками), вы открываете себя для потенциальной погрешности 22 см (если изначально тоже 11 см). Добровольно, вероятно, для этого нужно выполнить 64-разрядный расчет, прежде чем, возможно, сохранить в 3-й раз - теперь окно с погрешностью 33 см, + -16 см. Звучит глупо, имхо.
Штормград

@ Рик Джеймс Я бы, вероятно, сохранил его как 64-битный, т.е. 0,3333333333333333. Мы говорим о геоданных, верно? «1/3» редко появляется в природе, где вещи обычно измеряются с разумной точностью.
Штормград

4

TL; DR

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


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

Формат

  • градусы минуты секунды : 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, 21.278081 8 и X, 21.278081 9 составляет 1 см . Таким образом, 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 цифр для показателя степени) будет достаточно.

Поэтому здесь я бы хотел поддержать Аликс Акселя из комментариев о том, что предложение 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 бита)


3

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


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

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

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

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



-2

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


1
и float, и десятичные типы имеют свое место. как правило, числа с плавающей точкой означают физические переменные, а десятичные дроби - для счетных сущностей (в основном, для денег). я не понимаю, почему вы предпочитаете десятичную для длинных / длинных
Хавьер

1
Я также думаю, что float подходит для lat / long. По крайней мере, на SQL Server (4 байта, 7 цифр).
Драголюб Курчич

Поплавок не точен по оценкам, озеро точности в лат длинно смертельно! Это может указать вам на совершенно другое место на земном шаре.
HLGEM

2
Максимальная ошибка типов данных с плавающей точкой достаточно низка, чтобы это не было проблемой. Я имею в виду, вы все равно должны знать о умножении / накоплении ошибок в обеих реализациях.
Spidey

@HLGEM - Округление до некоторого числа десятичных разрядов также приводит вас в другое место на земном шаре. Вопрос в том, находится ли это другое место так близко, что это не имеет значения.
Рик Джеймс

-3

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

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

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


2
Вам нужен реальный широту / долготу координатный тип данных для легкой математики. Представьте себе удобство чего-то вроде эквивалента «выбрать * из магазинов, где расстояние (stores.location, mylocation) <5 миль»
Кирк Страусер,

1
Раньше я не слышал о пространственных расширениях, это звучит очень удобно, ведь ранее он работал над унаследованным приложением, которое выполняет довольно мало вычислений, связанных с географией, и должен это проверить.
ConroyP

@ConroyP - Нет. Эта цитата указывает, что DECIMALимелись (до 5.0.3) определенные ошибки из-за использования плавающей реализации.
Рик Джеймс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.