ANSI SQL準拠のデータベースに緯度または経度データを格納する場合、どのデータ型が最も適していますか? float
、またはdecimal
、または...を使用する必要がありますか?
Oracle、MySql、およびSQL Serverでは、特に地理データの処理用に特別なデータ型がいくつか追加されていますが、私はどのようにして情報を「単純なVanilla」SQLデータベースに格納するのかに関心があります。
Decimal(9,6)
パラメータの精度とスケールに慣れていない場合は、フォーマット文字列visualを次に示します。
###.######
Floatを使用しますが、小数点以下6桁の数値でも問題ありません。
次の変換アルゴリズムを使用して、整数部分と小数部分に分割して、ここで推奨されているように別々に格納する代わりに、緯度/経度の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
これはnsigned 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拡張機能がなく、単にこれらの緯度/経度のペアを数百万個保持したい場合は、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 */
Vanilla Oracleでは、LOCATOR(Spatialの機能不全バージョン)と呼ばれる機能を使用するには、座標データをNUMBER(精度なし)のデータ型を使用して格納する必要があります。空間クエリをサポートするために関数ベースのインデックスを作成しようとすると、そうでなければギャグになります。
SQL Server 2008で導入された新しいSpatialデータ型に注目してください。これらは特にこの種のタスクを設計し、データの索引付けと照会をはるかに簡単かつ効率的にします。
http://msdn.Microsoft.com/ja-jp/library/bb933876(v = sql.105).aspx
http://blogs.technet.com/andrew/archive/2007/11/26/sql-server-2008-spatial-data-types.aspx
私はあなたのデータに適切な精度の10進数を使います。
私はそれがあなたが最も頻繁にする必要があるであろう操作に依存すると思います。
完全な値を10進数として必要な場合は、適切な精度と位取りを持つdecimalを使用してください。フロートはあなたのニーズをはるかに超えています。
度分数表記に変換する場合は、各値を整数型(smallint、tinyint、tinyint、smallint?)として格納することを検討します。