メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL での IP 位置情報は、IP 範囲を場所に対応付けるデータベースをインポートし、範囲チェックで問い合わせることで動作します。標準的な手法は IP 範囲を整数として保存し、BETWEEN を使います。VillageSQL の INET 型はスキーマをより表現豊かにし、IPv4 と IPv6 を同じテーブルで扱います。

IP 位置情報の仕組み

IP を国に対応付ける MySQL の関数はありません。位置情報は検索の問題です。IP 範囲のテーブルがあり、各行が「X から Y までのアドレスは国 Z にある」と示していて、受信した IP を含む範囲を見つけます。 MaxMind GeoLite2 のような無料のデータベースは、これらの範囲を MySQL にインポートできる CSV ファイルとして提供しています。

標準的な手法: 整数の範囲

MaxMind GeoLite2(および同様のデータベース)は、network を CIDR 文字列として、各範囲の開始/終了を整数として提供しています。整数の手法はコンパクトで、インデックスに適しています。
これは高速です。start_ip のインデックスが効率的な範囲スキャンを可能にします。制限は、IPv4 でしか動作しないことです。IPv6 には別のテーブル(VARBINARY(16) の範囲を持つ)が必要です。

VillageSQL の場合: INET による IPv4/IPv6 の統合

VillageSQL の INET 型は、IPv4 と IPv6 の両方のアドレスを自然な順序で保存するため、両方のファミリーに 1 つのテーブルを使えます。範囲チェックでは inet_compare() が BETWEEN の役割を果たします。

CIDR ネットワークで保存する(代替スキーマ)

GeoIP データが開始/終了のペアではなく CIDR ブロックを提供している場合は、ネットワーク列に CIDR を使い、サブネットのクエリで包含を解決します。

手法の選択

IPv4 のみで最大のクエリ速度が必要なら、INT UNSIGNED + BETWEEN の手法に勝つのは困難です。IPv4 と IPv6 の両方を 1 つのテーブルで扱う必要があるスキーマでは、INET と inet_compare のほうが簡潔で、2 つの並行するテーブルを維持せずに済みます。

位置情報データソースの比較

クエリのスキーマは決定の半分に過ぎません。データソースが精度、鮮度、およびコストを決めます。一般的な選択肢の比較は次のとおりです。 国レベルの精度の数値はプロバイダーの自己申告であり、地域によって異なります。アジア太平洋とラテンアメリカのカバレッジは、すべてのソースで北米とヨーロッパより低い傾向があります。 どれを選ぶか: MaxMind GeoLite2 が標準的な出発点です。無料で、一度インポートするフラットファイルとして提供され、検索は外部依存なしに完全に MySQL の中で実行されます。本番環境で都市レベルの精度が必要なら、GeoIP2 Precision がアップグレードの道です。API ベースのソース(ip-api.com、ipinfo.io)は少量の利用には便利ですが、すべての検索に HTTP のレイテンシとレート制限への依存を加えます。

各手法を使う場面

GeoLite2 データのインポート

MaxMind GeoLite2(無料、登録が必要)は CSV ファイルを提供しています。範囲ベースのスキーマの場合は次のとおりです。
MaxMind はバイナリの .mmdb 形式と、Python、Node.js、Go などの言語向けの公式クライアントライブラリも提供しており、大量の検索を行うシナリオでは SQL の検索より高速です。

よくある質問

位置情報は MySQL とアプリケーションコードのどちらで行うべきですか?

大量の検索(すべての HTTP リクエスト)では、MaxMind の .mmdb リーダーライブラリを使ったアプリケーション層の位置情報のほうが高速です。メモリ内の二分探索で、SQL の往復がありません。SQL ベースの位置情報は、バッチ分析、レポートのクエリ、およびすでに MySQL で実行されているデータパイプラインに向いています。

GeoIP データベースを最新に保つにはどうすればよいですか?

MaxMind は GeoLite2 を毎週更新します。定期的なダウンロードと、位置情報テーブルの TRUNCATE + 再読み込みをスクリプト化してください。あるいは、MaxMind の mmdbinspect か更新スクリプトを使って差分更新を適用します。

MySQL での IP 位置情報はどのくらい正確ですか?

精度は MySQL のスキーマではなく、データソースだけで決まります。国レベルでは、MaxMind GeoLite2(無料)は IPv4 アドレスのおよそ 98% で正確です。都市レベルでは約 80% に下がります。より高い精度には、MaxMind の有料製品 GeoIP2 Precision が国で約 99.8%、都市で約 85〜90% に達します。完璧なデータベースはありません。精度は通常、モバイルネットワーク、VPN、および一部のアジア太平洋の範囲で低くなります。MySQL のクエリ手法は精度に影響しません。インポートしたデータが示すとおりの結果が得られます。

MySQL はプラグインや外部 API なしで IP 位置情報を検索できますか?

はい。標準的な手法、つまりこのガイドが扱う手法は、GeoIP データベース(MaxMind GeoLite2 など)を整数の範囲として通常の MySQL テーブルにインポートします。検索はただの SQL の BETWEEN クエリです。プラグインも、外部 API も、クエリ時のネットワーク呼び出しもありません。唯一の依存は、MaxMind のフラットな CSV ファイルをインポートし、定期的に更新することです。VillageSQL の vsql_network_address 拡張機能は、より簡潔な IPv4/IPv6 の扱いのために INET 型を追加しますが、基本的な手法には必須ではありません。

位置情報とアクセスログを 1 つのクエリで結合できますか?

はい。それが GeoIP データを MySQL に置く主な理由の 1 つです。

トラブルシューティング

関連項目