緯度と経度のペアで計算を実行することを念頭に置いて、MySQLデータベースでの使用に最適なデータ型はどれですか?
21 に答える
MySQLの空間拡張をGISで使用します。
基本的には、場所に必要な精度によって異なります。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
お役に立てれば。
Google は、Google マップを使用した「Store Locator」アプリケーションの例として、最初から最後まで PHP/MySQL ソリューションを提供しています。この例では、緯度/経度の値を長さ「10,6」の「浮動小数点数」として保存します。
MySQL の Spatial Extensions は、空間演算子とインデックスの完全なリストを自由に使用できるため、最適なオプションです。空間インデックスを使用すると、距離ベースの計算を非常に迅速に実行できます。6.0 の時点では、Spatial Extension はまだ不完全であることに注意してください。私は MySQL Spatial を下に置くつもりはありません。これに取り掛かる前に落とし穴を知らせているだけです。
ポイントを厳密に扱っており、DISTANCE 関数のみを扱っている場合は、これで問題ありません。Polygons、Lines、または Buffered-Points を使用して計算を行う必要がある場合、「relate」演算子を使用しない限り、空間演算子は正確な結果を提供しません。21.5.6の上部にある警告を参照してください。含む、内、または交差などの関係は、正確なジオメトリ形状ではなく、MBR を使用しています (つまり、楕円は長方形のように扱われます)。
また、MySQL Spatial の距離は、最初のジオメトリと同じ単位です。これは、10 進度を使用している場合、距離の測定値が 10 進度であることを意味します。これにより、赤道から離れるにつれて正確な結果を得ることが非常に難しくなります。
ARINC424 から構築されたナビゲーション データベースに対してこれを行ったとき、かなりの量のテストを行い、コードを振り返って、DECIMAL(18,12) (実際には NUMERIC(18,12) であったため、firebird でした) を使用しました。
float と double はそれほど正確ではなく、丸め誤差が発生する可能性があり、これは非常に悪いことです。問題のある実際のデータが見つかったかどうかは覚えていませんが、float または double に正確に格納できないことが問題を引き起こす可能性があることはかなり確信しています。
ポイントは、度またはラジアンを使用する場合、値の範囲を知っているということです。
MySQL Spatial Extensionsは、OpenGIS Geometry Modelに従っているため、優れた代替手段です。データベースの移植性を維持する必要があったため、それらを使用しませんでした。
必要な精度によって異なります。
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 を除く)。
ノート:
- classを使用する場合
POINT
、座標を格納するための引数の順序は である必要がありますPOINT(latitude, longitude)
。 - 空間インデックスを作成するための特別な構文があります。
- SDT を使用する最大の利点は、空間分析関数にアクセスできることです。たとえば、2 点間の距離の計算 (
ST_Distance
) や、ある点が別のエリア内に含まれているかどうかの判断 (ST_Contains
) などです。
この wiki 記事 http://en.wikipedia.org/wiki/Decimal_degrees#Accuracyに基づくと 、MySQL の適切なデータ型は Decimal(9,6) で、経度と緯度を別々のフィールドに格納します。
DECIMAL(8,6)
緯度 (90 ~ -90 度) とDECIMAL(9,6)
経度 (180 ~ -180 度) に使用します。ほとんどのアプリケーションでは、小数点以下 6 桁で問題ありません。両方とも、負の値を許可するために「署名」する必要があります。
緯度/経度X1,000,000をOracleデータベースにNUMBERSとして格納し、doubleによる丸め誤差を回避します。
小数点以下第6位までの緯度/経度が10cmの精度であったことを考えると、必要なのはそれだけでした。他の多くのデータベースも、緯度/経度を小数点以下6桁まで格納します。
まったく異なる、より単純な観点から:
- マップ、マーカー、ポリゴンなどを表示するために Google に依存している場合は、Google に計算を任せてください。
- サーバーにリソースを保存し、緯度と経度を単一の文字列 ( ) として保存するだけ
VARCHAR
です。 - Google が数値ごとに 7 桁を超える 10 進数を返す場合、将来、ハエや微生物を検出する場合に備えて、そのデータを文字列に保存することができます。
- 距離行列またはジオメトリ ライブラリを使用して、距離を計算したり、特定の領域のポイントを検出したりするには、次のように簡単に呼び出します。
google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
- Google Maps API を使用して使用できる「サーバー側」API はたくさんあります ( Python、Ruby on Rails、PHP、CodeIgniter、Laravel、Yii、Zend Frameworkなど)。
このようにして、インデックス番号や、座標を台無しにする可能性のあるデータ型に関連するその他すべての問題について心配する必要はありません。
すべての操作に最適というわけではありませんが、マップ タイルを作成したり、1 つの投影法 (Google マップや他の多くのスリッピー マップ フレームワークが期待するメルカトルなど) だけで多数のマーカー (ドット) を操作したりする場合、私は何を見つけましたか?私は「Vast Coordinate System」を本当に便利だと呼んでいます。基本的に、x と y のピクセル座標を何らかの方法でズームインして保存します。私はズーム レベル 23 を使用します。これにはいくつかの利点があります。
- ポイントを処理するたびに、高価な lat/lng からメルカトル ピクセルへの変換を 1 回実行します。
- ズーム レベルを指定してレコードからタイル座標を取得するには、1 つの右シフトが必要です。
- レコードからピクセル座標を取得するには、1 つの右シフトと 1 つのビットごとの AND が必要です。
- シフトは非常に軽量であるため、SQL で実行するのが実用的です。つまり、DISTINCT を実行して、ピクセル位置ごとに 1 つのレコードのみを返すことができます。これにより、バックエンドによって返されるレコード数が削減されます。つまり、フロントエンド。
このすべてについて、最近のブログ投稿で話しました: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/
アプリケーションによっては、FLOAT(9,6)を使用することをお勧めします
空間キーはより多くの機能を提供しますが、実稼働ベンチマークでは、フロートは空間キーよりもはるかに高速です。(AVGでは0,01 VS 0,001)
MySQL はすべての float に double を使用します。したがって、double 型を使用します。float を使用すると、ほとんどの状況で丸められた値が予測不能になります。
PostGISの空間関数は、MySQL空間関数の空間関数よりもはるかに機能的です(つまり、BBOX操作に制約されません)。それをチェックしてください:リンクテキスト
緯度経度の計算には精度が必要なため、数学計算を実行するには、ある種の10進数タイプを使用し、格納する数値よりも精度を2以上高くします。私のsqlデータ型についてはわかりませんが、SQLサーバーでは、10進数の代わりにfloatまたはrealを使用することが多く、これらは実際の数値ではなく推定値であるため、問題が発生します。したがって、使用するデータ型が浮動小数点型ではなく真の10進数型であることを確認してください。そうすれば、問題はありません。
AFLOAT
は、必要なすべての精度を提供し、各座標を文字列などとして格納するよりも、比較関数に適している必要があります。
ただし、MySQLのバージョンが5.0.3より前の場合は、特定の浮動小数点比較エラーに注意する必要があります。
MySQL 5.0.3より前では、DECIMAL列は文字列として表されるため、正確な精度で値を格納しますが、DECIMAL値の計算は浮動小数点演算を使用して行われます。5.0.3以降、MySQLは小数点以下64桁の精度でDECIMAL演算を実行します。これにより、DECIMAL列に関して最も一般的な不正確な問題が解決されます。