緯度または経度のデータをANSISQL準拠のデータベースに保存する場合、どのデータ型が最も適切でしょうか。float使用する必要があります、またはdecimal、または... ?
Oracle、MySql、およびSQL Serverが、地理データを処理するために特別なデータ型を追加したことは知っていますが、情報を「プレーンバニラ」SQLデータベースに格納する方法に興味があります。
緯度または経度のデータをANSISQL準拠のデータベースに保存する場合、どのデータ型が最も適切でしょうか。float使用する必要があります、またはdecimal、または... ?
Oracle、MySql、およびSQL Serverが、地理データを処理するために特別なデータ型を追加したことは知っていますが、情報を「プレーンバニラ」SQLデータベースに格納する方法に興味があります。
緯度の使用:Decimal(8,6)、および経度の使用:Decimal(9,6)
パラメータの精度とスケーリングに慣れていない場合は、次の形式の文字列を視覚的に確認できます。
緯度と経度
##.######と###.######
小数点以下6桁までは、座標で約10cmの精度になります。
floatを使用しますが、小数点以下6桁の任意の数値も機能するはずです。
私はあなたのデータに適切な精度の小数を使用します。
緯度/経度を保存する方法を尋ねられましたが、私の答えは次のとおりです。地理参照の標準であるWGS 84(ヨーロッパではETRS 89 )の使用を検討してください。
しかし、その詳細はさておき、SQL2008に最終的に地理サポートが含まれる前の数日間にユーザー定義型を使用しました。
バニラオラクルでは、LOCATOR(Spatialの機能不全バージョン)と呼ばれる機能では、座標データをNUMBER(精度なし)のデータ型を使用して格納する必要があります。空間クエリをサポートするために関数ベースのインデックスを作成しようとすると、それ以外の場合はギャグします。
SQL Server 2008で導入された新しい空間データ型を確認する必要があります。これらはこの種のタスク用に特別に設計されており、データのインデックス作成とクエリをはるかに簡単かつ効率的にします。
http://msdn.microsoft.com/en-us/library/bb933876(v=sql.105).aspx
緯度/経度の10進数は、整数と小数部分に分割して、次の変換アルゴリズムを使用してここで提案されているように別々に格納する代わりに、符号なし整数フィールドに簡単に格納できます。
保存された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
これはunsignedint(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 */
それはあなたが最も頻繁に行う必要がある操作に依存すると思います。
10進数として完全な値が必要な場合は、適切な精度とスケールで10進数を使用してください。フロートはあなたのニーズをはるかに超えていると私は信じています。
degºmin'sec"分数表記との間で頻繁に変換する場合は、各値を整数型(smallint、tinyint、tinyint、smallint?)として格納することを検討します。