VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
BETWEEN. VillageSQL’s INET type makes the schema more expressive and handles IPv4 and IPv6 in the same table.
How IP Geolocation Works
There’s no MySQL function that maps an IP to a country. Geolocation is a lookup problem: you have a table of IP ranges — each row says “addresses from X to Y are in country Z” — and you find which range contains the incoming IP. Free databases like MaxMind GeoLite2 provide these ranges as CSV files you import into MySQL.The Standard Approach: Integer Ranges
MaxMind GeoLite2 (and similar databases) ship withnetwork as a CIDR string and the start/end of each range as integers. The integer approach is compact and index-friendly:
start_ip enables efficient range scanning. The limitation is that it only works for IPv4. A separate table (with VARBINARY(16) ranges) is needed for IPv6.
With VillageSQL: Unified IPv4/IPv6 with INET
VillageSQL’sINET type stores both IPv4 and IPv6 addresses with natural ordering, so you can use a single table for both families. inet_compare() takes the place of BETWEEN for range checks.
Storing by CIDR network (alternative schema)
If your GeoIP data provides CIDR blocks rather than start/end pairs, useCIDR for the network column and resolve containment via subnet queries:
Choosing an Approach
For pure IPv4 and maximum query speed, the
INT UNSIGNED + BETWEEN approach is hard to beat. For schemas that need to handle both IPv4 and IPv6 in one table, INET with inet_compare is cleaner and avoids maintaining two parallel tables.
Comparing Geolocation Data Sources
The query schema is only half the decision — the data source determines accuracy, freshness, and cost. Here’s how the common options compare:
Country-level accuracy figures are self-reported by providers and vary by region — Asia-Pacific and Latin American coverage tends to be lower than North America and Europe across all sources.
Which to pick: MaxMind GeoLite2 is the standard starting point — it’s free, ships as flat files you import once, and lookups run entirely inside MySQL with no external dependency. For city-level accuracy in production, GeoIP2 Precision is the upgrade path. API-based sources (ip-api.com, ipinfo.io) are convenient for low-volume use but add HTTP latency and a rate-limit dependency to every lookup.
When to Use Each Approach
Importing GeoLite2 Data
MaxMind GeoLite2 (free, requires registration) provides CSV files. For the range-based schema:.mmdb format and official client libraries for languages like Python, Node.js, and Go that are faster than SQL lookups for high-volume scenarios.
Frequently Asked Questions
Should I do geolocation in MySQL or in application code?
For high-volume lookups (every HTTP request), application-layer geolocation using MaxMind’s.mmdb reader library is faster — binary search in memory, no SQL round-trip. SQL-based geolocation makes sense for batch analytics, reporting queries, and data pipelines that already run in MySQL.
How do I keep the GeoIP database current?
MaxMind updates GeoLite2 weekly. Script a periodic download andTRUNCATE + reload of the geolocation table. Alternatively, use MaxMind’s mmdbinspect or a refresh script to apply delta updates.
How accurate is IP geolocation in MySQL?
Accuracy depends entirely on the data source, not the MySQL schema. At the country level, MaxMind GeoLite2 (free) is accurate for roughly 98% of IPv4 addresses. At the city level it drops to around 80%. For higher accuracy, MaxMind’s paid GeoIP2 Precision product reaches ~99.8% country and ~85–90% city. No database is perfect — accuracy is typically lower for mobile networks, VPNs, and some Asia-Pacific ranges. The MySQL query approach has no effect on accuracy; you get exactly what the imported data says.Can MySQL look up IP geolocation without a plugin or external API?
Yes. The standard approach — and what this guide covers — uses a GeoIP database (like MaxMind GeoLite2) imported into a regular MySQL table as integer ranges. Lookups are plain SQLBETWEEN queries. No plugin, no external API, no network call at query time. The only dependency is importing and periodically refreshing the flat CSV files from MaxMind. VillageSQL’s vsql_network_address extension adds an INET type for cleaner IPv4/IPv6 handling, but it’s not required for the basic approach.
Can I join geolocation with my access logs in one query?
Yes — that’s one of the main reasons to keep GeoIP data in MySQL:Troubleshooting
See also
- Storing IP Addresses in MySQL — efficient IP storage before geolocation queries
- Querying by Subnet in MySQL — range-based IP lookups that geolocation builds on

