2011-12-06 4 views
0

ユーザ情報のあるテーブルとジオロケーションデータを持つテーブル(GeoIPのデータベース)との相互参照に問題があります。IP情報のサブクエリとインデックス付け

ユーザーテーブルには標準形式(整数ではない)のIPアドレスがあり、整数IP範囲ではGeoIPテーブルのGeoIPデータがあります。

このクエリは機能しますが、非常に遅く、最適化されません。

SELECT email, country 
FROM users 
INNER JOIN geoip ON users.ip BETWEEN geoip.startip AND geoip.endip 

私はここで非常に簡単なものが欠けているように感じます。

更新:このクエリは機能しますが、非常に遅いです。インデックスを作成する方法はありますか?今、実行するときに関係なく、各行は実行に約300〜500msかかるでしょう。これは遅すぎます。

SELECT email, country 
FROM users INNER JOIN geoip ON INET_ATON(users.ip) 
BETWEEN geoip.startip AND geoip.endip 

ありがとうございます!

UPDATE 2:ここでは、クエリにEXPLAIN出力です:私は今、整数のみのIP行を追加することはできません

+----+-------------+-----------+------+---------------+------+---------+------+----------+-------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows  | Extra  | 
+----+-------------+-----------+------+---------------+------+---------+------+----------+-------------+ 
| 1 | SIMPLE  | geoip  | ALL | NULL   | NULL | NULL | NULL | 3651972 |    | 
| 1 | SIMPLE  | users  | ALL | NULL   | NULL | NULL | NULL | 87996123 | Using where | 
+----+-------------+-----------+------+---------------+------+---------+------+----------+-------------+ 

DBの使用で、それは90万行のだから。私は何らかのダウンタイムの間にやっていることに気がついていますが、今はこのように動作させたいと思います。私はまだコメントできません

答えて

2

ので、ここで「答えが」だ...

は、あなたはそれが動作しますか?あなたの記述が正しく理解されていれば、charまたはvarcharのCIDR表記でusers.ip、整数としてgeoip.startip/endipがあります。したがって、このクエリはこれらの2つを正しく比較する方法がありません。これを行うための

正しい方法はかなり大きい(複数の行)がテーブルに応じて、より良い一つである

SELECT email, country 
FROM users INNER JOIN geoip ON INET_ATON(users.ip) 
BETWEEN geoip.startip AND geoip.endip 

または

SELECT email, country 
FROM users INNER JOIN geoip ON users.ip 
BETWEEN INET_NTOA(geoip.startip) AND INET_NTOA(geoip.endip) 

のどちらかだろう。

これを行う最も良い方法は、users.ipを整数(または整数解釈のある別の列)として保存することです。

+0

最初のクエリは機能しますが、非常に遅いです - インデックスを作成してより速く実行できる方法はありますか?今のところ、1行につき少なくとも300〜500msかかる。 –

+0

geoip.startipとgeoip.endipにインデックスがありますか? – Fox

+0

はい、また、startip、endip、countryのインデックスも一緒です。 –

関連する問題