Inspired by Jeremy Cole and Andy Skelton articles about efficient MySQL GeoIP implementation.
Obvious but Bad query:
SELECT `code`, `country`
FROM `geoip_countries`
WHERE INET_ATON('4.2.2.1') BETWEEN `ip_from` AND `ip_to`
As rule MySQL cannot use index for such request.
Good query:
SELECT `code`, `country`
FROM `geoip_countries`
WHERE `ip_to` >= INET_ATON('4.2.2.1')
ORDER BY `ip_to` ASC
LIMIT 1
(Alternatively you can use ip_from <= addr
and ORDER BY ip_from DESC
. But I prefer ascending sort :) )
Ok then. But there is a nuance! GeoIP table had gaps between some ranges and decided to rectify this condition by filling in the gaps with "no country" rows, ensuring that the query would return "no country" instead of a wrong country.
Another bad thing is some tables has not unicode characters. So before import we should convert it. This instruction helps you to fix both
Download and unzip free Maxmind GeoIP files:
- GeoLite Country,
- GeoLite City and
- GeoLite ASN.
Then run from console:
iconv -f ISO-8859-15 -t UTF-8 GeoLiteCity-Location.csv > GeoLiteCity-Location-UTF8.csv
iconv -f ISO-8859-15 -t UTF-8 GeoIPASNum2.csv > GeoIPASNum2-UTF8.csv
php nogap.php country GeoIPCountryWhois.csv > GeoIPCountryWhois-nogaps.csv
php nogap.php blocks GeoLiteCity-Blocks.csv > GeoLiteCity-Blocks-nogaps.csv
php nogap.php asnum GeoIPASNum2-UTF8.csv > GeoIPASNum2-UTF8-nogaps.csv
Now you are ready to import it into MySQL. There are scheme and data load files for you.
Regards,
Alexandr a.k.a. artoodetoo