Edited at

MySQLに緯度経度を保存する際の、カラム型の選び方

More than 3 years have passed since last update.


はじめに

数値を丸められること無く、記録したとおりに緯度経度情報を保存したい。

もちろん文字列型ではなく浮動小数点型を使う方が処理効率が良いですよね。

どのようなカラムを使えば意図通りに保存出来るのかまとめてみました。


結論

VARCHAR型やDECIMAL型を利用する手もありますが、どちらも計算コストが高いため、

基本的にdouble(9,6)を利用すれば問題ないでしょう。


最大値と最小値

それぞれの最小値と最大値は次の通りです。


  • 緯度 (latitude) : -90 〜 90

  • 経度 (longitude) : -180 〜 180


小数点桁数と精度の関係

どの程度の精度を求めるには、どの程度の桁数が必要となるか、まとめてみましょう。


ざっくりと計算しますと地球の円周は約40,000,000mで

緯度はぐるっと360度ですから緯度1度は

40000000/360≒111111.1111...

で約111,111mになります。

経度緯度のDBカラムの桁数 【OKWave】

http://okwave.jp/qa/q4506558.html


こちらを表にすると、次の通りです。5〜6桁もあれば日常のユースケースに対応出来そうですね。

小数点以下桁数
緯度
概算距離
MySQLのカラム型 (緯度/lat)
MySQLのカラム型 (経度/lng)

0
1度
111km
double(2,0)
double(3,0)

1
0.1度
11km
double(3,1)
double(4,1)

2
0.01度
1111m
double(4,2)
double(5,2)

3
0.001度
111m
double(5,3)
double(6,3)

4
0.0001度
11m
double(6,4)
double(7,4)

5
0.00001度
1m
double(7,5)
double(8,5)

6
0.000001度
11cm
double(8,6)
double(9,6)

7
0.0000001度
1cm
double(9,7)
double(10,7)

カラムの引数は double(桁数, 小数点以下の桁数) という指定となっています。


スキーマ例

緯度経度を格納するテーブルのスキーマ例は次の通りです。

ただ、緯度経度それぞれの型を共通化しておきたい場合には、大きい方のdouble(9,6)に合わせると良いでしょう。

CREATE TABLE `geo_locations` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`lat` double(8,6) DEFAULT NULL,
`lng` double(9,6) DEFAULT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

さらに空間情報インデックス(geometory index)を付与して検索する際には、次のようにスキーマをセットします。

MySQL 5.7からは対応していますが、それ以前のバージョンではInnoDBはSPATIALインデックス非対応です。


そのため、MySQL 5.0/5.1/5.5/5.6環境で高速に検索できるようにする場合には、次のようにスキーマをセットする必要があります。

CREATE TABLE `geo_locations` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`location` geometry NOT NULL, -- NOT NULLである必要があります
PRIMARY KEY (`id`),
SPATIAL KEY `geo_location` (`location`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

バージョン問わずInnoDBで緯度経度検索を高速に行う場合は、B-Treeインデックスの使えるGeoHash形式を使うと良いです。

http://d.hatena.ne.jp/hiratara/20100824/1282635611


あわせて読みたい