緯度/経度のペアで計算を実行することを念頭に置いて、MySQLデータベースでの使用に最適なデータ型は何ですか?
緯度/経度のペアで計算を実行することを念頭に置いて、MySQLデータベースでの使用に最適なデータ型は何ですか?
回答:
MySQLの空間拡張をGISで使用します。
Googleは、Google Mapsを使用したサンプルの「店舗検索」アプリケーションのPHP / MySQLソリューションを最初から最後まで提供します。この例では、緯度/経度の値を「Float」として長さ「10,6」で保存しています。
FLOAT(10,6)
。座標の整数部分には4桁を残します。そして、いいえ、符号はカウントされません-これは、(署名されていない)属性に由来します。
Double
Laravelのデータ型の使用
基本的には、場所に必要な精度によって異なります。DOUBLEを使用すると、3.5nmの精度になります。DECIMAL(8,6)/(9,6)は16cmになります。FLOATは1.7m ...
この非常に興味深いテーブルには、より完全なリストがあります: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
お役に立てれば。
MySQLの空間拡張は、空間演算子とインデックスの完全なリストを自由に利用できるため、最適なオプションです。空間インデックスを使用すると、距離ベースの計算をすばやく実行できます。6.0の時点では、Spatial Extensionはまだ不完全であることを覚えておいてください。私はMySQL Spatialを書き下ろすのではなく、これに取り掛かる前に落とし穴を知らせているだけです。
ポイントを厳密に扱い、DISTANCE関数のみを扱う場合は、これで問題ありません。ポリゴン、ライン、またはバッファポイントを使用して計算を行う必要がある場合、「relate」演算子を使用しない限り、空間演算子は正確な結果を提供しません。21.5.6の上部にある警告を参照してください。包含、内部、交差などの関係は、正確なジオメトリ形状ではなくMBRを使用しています(つまり、楕円は長方形のように扱われます)。
また、MySQL Spatialの距離は最初のジオメトリと同じ単位です。つまり、10進度を使用している場合、距離の測定値は10進度になります。これは、赤道から遠方に行くため、正確な結果を得ることが非常に難しくなります。
ARINC424から構築されたナビゲーションデータベースに対してこれを行ったとき、かなりの量のテストを行い、コードを振り返ると、DECIMAL(18,12)(実際は火の鳥なのでNUMERIC(18,12))を使用しました。
floatとdoubleは正確ではなく、非常に悪い丸め誤差を引き起こす可能性があります。問題のある実際のデータを見つけたかどうかは思い出せませんが、floatまたはdoubleに正確に格納できないと問題が発生する可能性があることはかなり確実です
重要なのは、度またはラジアンを使用する場合、値の範囲がわかっていることであり、小数部には最も多くの桁が必要です。
MySQLの空間拡張機能は、彼らが続くので、良い代替されているのOpenGISジオメトリモデル。データベースを移植可能な状態に保つ必要があるため、使用しませんでした。
a*b
等しくないマシン上にもありましたb*a
。次のような例が多数ありました2+2 = 3.9999
。この規格は多くの混乱を解消し、事実上すべてのハードウェアとソフトウェアに「迅速に」採用されました。したがって、この議論は2008年以来だけでなく、3世紀にわたって有効です。
必要な精度に依存します。
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はインデックスをサポートしていません(テーブルタイプがMyISAMの場合は5.6を除く)。
注意:
POINT
クラスを使用する場合、座標を格納するための引数の順序はでなければなりませんPOINT(latitude, longitude)
。ST_Distance
)、1つのポイントが別のエリア内に含まれているかどうかを判断できます(ST_Contains
)。CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;
、Jamesが述べたように、SDTの制限に関する警告のような例をさらに追加した場合、それらを使い始めたい人々にとって実際に役立ちます。 ..
このWiki記事http://en.wikipedia.org/wiki/Decimal_degrees#Accuracyに基づいて 、MySQLの適切なデータ型は、経度と緯度を別々のフィールドに格納するためのDecimal(9,6)です。
Googleマップによると、緯度と経度の場合はFLOAT(10,6)が最適です。
lat FLOAT( 10, 6 ) NOT NULL,
lng FLOAT( 10, 6 ) NOT NULL
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-を
緯度/経度X 1,000,000をoraclesデータベースにNUMBERSとして保存し、doubleによる丸めエラーを回避しています。
小数点以下6桁までの緯度/経度が10 cmの精度であるとすれば、それで十分でした。他の多くのデータベースも緯度/経度を小数点第6位まで格納しています。
完全に異なる、より単純な視点で:
VARCHAR
)として一緒に保存するだけです。例: " -0000.0000001、-0000.000000000000001」(35の長さと数を超える7桁を持っている場合、それは丸い取得します)。google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
これにより、インデックスの番号や、座標をめちゃくちゃにする可能性のあるデータ型に関連する他のすべての問題について心配する必要がなくなります。
アプリケーションによっては、FLOAT(9,6)の使用をお勧めします
空間キーはより多くの機能を提供しますが、生産ベンチマークではフロートは空間キーよりもはるかに高速です。(AVGで0,01対0,001)
MySQLはすべてのフロートにdoubleを使用します...したがって、doubleタイプを使用します。floatを使用すると、ほとんどの状況で予測できない丸められた値が発生します
DOUBLE
ます。MySQLでは、データを4バイトまたは8 バイトとして格納できます。そのため、式を列に格納すると精度が失われる可能性があります。FLOAT
DOUBLE
FLOAT
すべての操作に最適なわけではありませんが、マップタイルを作成するか、1つの投影のみで多数のマーカー(ドット)を操作する場合(たとえば、Googleマップのようなメルカトルや他の多くの滑りやすいマップフレームワークが期待する)、私は何を見つけました私は「広大な座標系」を本当に便利なものと呼んでいます。基本的に、xとyのピクセル座標を何らかの方法でズームインして保存します-私はズームレベル23を使用します。これにはいくつかの利点があります:
私は最近のブログ投稿でこれらすべてについて話しました:http : //blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/
私はいくつかの回答/コメントに非常に驚いています。
いったいなぜ、誰かが自発的に精度を「事前に低下」させ、その後、より悪い数値に対して計算を実行しようとするのでしょうか。最終的に愚かに聞こえます。
ソースの精度が64ビットの場合、自発的にスケールをたとえばに固定するのは無意味です。小数点以下6桁、精度を最大9桁の有効桁数に制限します(これは、一般的に提案されている10進数9.6形式で発生します)。
当然、データはソースマテリアルの精度で保存されます。精度を下げる唯一の理由は、限られた保管スペースです。
10進数の9.6形式は、グリッドにスナップする現象を引き起こします。それが発生したとしても、それが最後のステップになるはずです。
蓄積されたエラーを巣に招くことはありません。
TL; DR
NASA /軍隊で作業しておらず、航空機のナビゲーションシステムを作成していない場合は、FLOAT(8,5)を使用します。
質問に完全に答えるには、いくつかの点を考慮する必要があります。
フォーマット
したがって、答えの最初の部分は、アプリケーションが使用する形式で座標を保存して、一定の相互変換を回避し、より単純なSQLクエリを作成することです。
ほとんどの場合、GoogleマップまたはOSMを使用してデータを表示し、GMapは「10進度2」形式を使用しています。したがって、座標を同じ形式で格納する方が簡単です。
精度
次に、必要な精度を定義します。もちろん、「-32.608697550570334,21.278081997935146」のような座標を保存できますが、ポイントまでのナビゲーション中にミリメートルを気にすることはありますか?NASAで作業しておらず、衛星、ロケット、飛行機の軌道を使用していない場合は、数メートルの精度で問題ありません。
一般的に使用される形式は、ドットの後に5桁あり、50cmの精度が得られます。
例:X、21.278081 8とX、21.278081 9の間には1cmの距離がありますます。したがって、ドットの後の7桁は1 / 2cmの精度を提供し、ドットの後の5桁は1/2メートルの精度を提供します(異なる点間の最小距離は1mであるため、丸め誤差はその半分を超えることはできません)。ほとんどの民事目的にはそれで十分です。
度の小数形式(40°26.767 ′N 79°58.933′ W)は、ドットの後の5桁とまったく同じ精度を提供します
スペース効率の良いストレージ
10進形式を選択した場合、座標はペアになります(-32.60875、21.27812)。明らかに、2 x(符号は1ビット、度は2桁、指数は5桁)で十分です。
だからここで私はFLOAT(10,6)に保存するためのGoogleの提案が本当に余分であると言っているコメントからAlix Axelをサポートしたいと思い ます。 90に、経度は180に制限されます)。1 / 2m精度のFLOAT(8,5)または50 / 2cm精度のFLOAT(9,6)を簡単に使用できます。または、latにはFLOAT(7,5)で十分なので、latとlongを別々の型で格納することもできます。MySQL float型のリファレンスを参照してください。それらのいずれも通常のFLOATのようになり、いずれにしても4バイトになります。
通常、今日の容量は問題ではありませんが、何らかの理由でストレージを本当に最適化したい場合は(免責事項:事前最適化を行わないでください)、lat(91 000以下の値+符号)+ long(no 181 000を超える値+符号)から21ビットに、2xFLOAT(8バイト== 64ビット)を大幅に下回る
SQL ServerにはFloatデータ型を使用することをお勧めします。
Lat Long計算には精度が必要なため、ある種の10進数型を使用し、数学計算を実行するために格納する数値よりも精度を少なくとも2高くします。私のsqlデータ型はわかりませんが、SQLサーバーでは、10進数の代わりにfloatまたはrealを使用することが多く、これらは実数ではなく推定値であるため、問題が発生します。したがって、使用するデータ型が浮動小数点型ではなく、真の10進数型であることを確認してください。問題はありません。
A FLOAT
は必要な精度をすべて提供し、各座標を文字列などとして保存するよりも比較関数に適しています。
ただし、MySQLバージョンが5.0.3より前の場合は、特定の浮動小数点比較エラーに注意する必要があります。
MySQL 5.0.3より前では、DECIMALカラムは文字列として表されるため、正確な精度で値を格納しますが、DECIMAL値の計算は浮動小数点演算を使用して行われます。5.0.3以降、MySQLは10進数64桁の精度でDECIMAL操作を実行します。これにより、DECIMALカラムに関して最も一般的な不正確な問題が解決されます。
DECIMAL
、浮動実装の使用による特定のエラー(5.0.3より前)があったことを指摘しています。