Ответ 1
Decimal(9,6)
Если вы не используете параметры точности и масштабирования, здесь отображается строка формата:
###.######
При хранении данных широты или долготы в базе данных, совместимой с ANSI SQL, какой тип данных был бы наиболее уместным? Если используется float
или decimal
, или...?
Я знаю, что Oracle, MySql и SQL Server добавили некоторые специальные типы данных специально для обработки геоданных, но меня интересует, как вы будете хранить информацию в базе данных "plain vanilla" SQL.
Decimal(9,6)
Если вы не используете параметры точности и масштабирования, здесь отображается строка формата:
###.######
Мы используем float, но любой вкус числового с шестью десятичными разрядами также должен работать.
В vanilla Oracle функция LOCATOR (искаженная версия Spatial) требует, чтобы данные координат сохранялись с использованием типа данных NUMBER (без точности). Когда вы пытаетесь создать функциональные индексы для поддержки пространственных запросов, это будет gag иначе.
Вы можете легко сохранить десятичное число lat/lon в целочисленном поле без знака вместо того, чтобы разбивать их в целочисленной и десятичной части и хранить их отдельно, как это предлагается здесь, используя следующий алгоритм преобразования:
как хранимая функция mysql:
CREATE DEFINER=`r`@`l` FUNCTION `PositionSmallToFloat`(s INT)
RETURNS decimal(10,7)
DETERMINISTIC
RETURN if( ((s > 0) && (s >> 31)) , (-(0x7FFFFFFF -
(s & 0x7FFFFFFF))) / 600000, s / 600000)
и назад
CREATE DEFINER=`r`@`l` FUNCTION `PositionFloatToSmall`(s DECIMAL(10,7))
RETURNS int(10)
DETERMINISTIC
RETURN s * 600000
Это необходимо сохранить в unsigned int (10), это работает как в mysql, так и в sqlite, который является безликим.
через опыт, я нахожу, что это работает очень быстро, если все, что вам нужно, это хранить координаты и извлекать их для выполнения некоторой математики.
в php эти 2 функции выглядят как
function LatitudeSmallToFloat($LatitudeSmall){
if(($LatitudeSmall>0)&&($LatitudeSmall>>31))
$LatitudeSmall=-(0x7FFFFFFF-($LatitudeSmall&0x7FFFFFFF))-1;
return (float)$LatitudeSmall/(float)600000;
}
и обратно:
function LatitudeFloatToSmall($LatitudeFloat){
$Latitude=round((float)$LatitudeFloat*(float)600000);
if($Latitude<0) $Latitude+=0xFFFFFFFF;
return $Latitude;
}
Это имеет некоторые дополнительные преимущества и в плане создания, например, memcached уникальных ключей с целыми числами. (например: кеширование результата геокода). Надеюсь, что это добавит ценность для обсуждения.
Другое приложение может быть, когда вы без расширений GIS и просто хотите сохранить несколько миллионов этих пар lat/lon, вы можете использовать разделы в этих полях в mysql, чтобы извлечь выгоду из того, что они являются целыми числами:
Create Table: CREATE TABLE `Locations` (
`lat` int(10) unsigned NOT NULL,
`lon` int(10) unsigned NOT NULL,
`location` text,
PRIMARY KEY (`lat`,`lon`) USING BTREE,
KEY `index_location` (`locationText`(30))
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY KEY ()
PARTITIONS 100 */
Я бы использовал десятичную цифру с правильной точностью для ваших данных.
Я думаю, что это зависит от операций, которые вам понадобятся делать чаще всего.
Если вам нужно полное значение как десятичное число, используйте десятичное значение с соответствующей точностью и масштабированием. Полагаю, что поплавок намного превосходит ваши потребности.
Если вы часто будете конвертировать в/из деградации ° deg ° min'sec, я бы рассмотрел сохранение каждого значения в виде целочисленного типа (smallint, tinyint, tinyint, smallint?).
Ну, вы спросили, как хранить Локатор/Долгота, и мой ответ: Не используйте, вы можете использовать WGS 84 ( в Европе ETRS 89), поскольку это стандарт для ссылок Geo.
Но в этой части я использовал User Defined Type за несколько дней до того, как SQL 2008, наконец, включит поддержку geo.
Вы должны взглянуть на новые типы пространственных данных, которые были введены в SQL Server 2008. Они специально разработаны для такого рода задач и делают индексацию и запрос данных намного проще и эффективнее.
http://msdn.microsoft.com/en-us/library/bb933876(v=sql.105).aspx
http://blogs.technet.com/andrew/archive/2007/11/26/sql-server-2008-spatial-data-types.aspx