Geospatial Databases & Spatial Indexing
How do apps like Uber, Yelp, Google Maps, and Tinder find drivers or restaurants within 2 km in less than 5 milliseconds? Learn why 2D maps break traditional databases, and master Geohashes, QuadTrees, and Google S2 from first principles.
๐บ๏ธ 1. Why Normal Databases Can't Search Maps
Think of a traditional database index (like a B-Tree) as an alphabetical dictionary.
If you search for words starting with "Cat", the dictionary is lightning fast because words are arranged along a single, sorted 1D line (from A to Z).
But what happens when you ask a dictionary: "Find all words located within 2 miles of Central Park"?The dictionary is completely useless! It only knows how to sort in 1 dimension (alphabetical), but the real world has 2 dimensions:
Measures how far North or South you are from the Equator.
Measures how far East or West you are from the Prime Meridian.
SELECT * FROM restaurants
WHERE lat BETWEEN 37.70 AND 37.80 AND lng BETWEEN -122.50 AND -122.40;If you index latitude, the database searches a narrow horizontal band that wraps around the entire planet! It looks through millions of restaurants in Tokyo, Seoul, San Francisco, and Athens before it can filter out the longitude.
(lat, lng) into a single 1D number or string so that places that are close on the map get codes that are close in the database!โ๏ธ 2. Geohash: Turning the World into a Chessboard
Have you ever played the game Battleship or chess? Instead of saying "My piece is 4.5 inches from the left", you say "E4".
A Geohash does the exact same thing for the whole planet. It cuts the Earth into a grid of boxes, giving each box a short code name (like "9q8yy").
1, South = 0).1, West = 0)."9q8yy").๐ Longer Code = Higher Zoom Level
The beauty of Geohash is that adding more letters zooms into a smaller, tighter box:
| Geohash Length | Size of the Box | What it Represents | Example Code |
|---|---|---|---|
| 1 letter | ~5,000 km | An entire continent (e.g. North America) | 9 |
| 4 letters | ~39 km ร 20 km | A whole metropolitan area (SF Bay Area) | 9q8y |
| 5 letters | ~4.9 km ร 4.9 km | A city or large district | 9q8yy |
| 6 letters | ~1.2 km ร 0.6 km | Uber & Yelp sweet spot: Local neighborhood blocks | 9q8yyz |
| 8 letters | ~38 meters | A specific building or street corner | 9q8yyz3p |
Imagine you live in Apartment #199. Your friend lives in Apartment #200 right across the hallway โ literally 2 steps away.
Even though you are 1 meter apart, your door numbers start with different digits (1 vs 2). If a food delivery app only searches apartments starting with "1", it will completely miss your friend!
๐ณ 3. QuadTrees: The "Smart Zoom" Tree for Moving Cars
Fixed Geohash grids have one big flaw: a 1 km box in the desert has 0 cars, while a 1 km box in Times Square, New York has 25,000 cars!
A QuadTree solves this by dynamically adapting to population density:
Start with 1 big box for the city. If a box gets more than 100 drivers, automatically split it into 4 smaller quadrants (North-West, North-East, South-West, South-East).
Uber drivers move every 4 seconds. Updating disk databases 1,000,000 times per second would melt the hard drives! QuadTrees live entirely in RAM for sub-millisecond updates.
๐ 4. Google S2: The Space-Filling Snake (64-Bit Numbers)
Imagine laying a single continuous piece of thread (a Hilbert Curve) that snakes through every room in a house without ever crossing itself. If two rooms are next to each other in the house, they are right next to each other on the thread!
Google developed Google S2 (used by Uber, Tinder, and Google Maps) which maps every spot on Earth to a clean 64-bit integer:
1029384) 10x faster than comparing text strings ("9q8yyz").WHERE s2_id BETWEEN 5000 AND 5050.โ๏ธ 5. Cheat Sheet: Which Spatial Index to Choose?
| Tool | Where it Lives | Best For | Real-World Example |
|---|---|---|---|
| Geohash (Base32) | Database / Redis | Static places that don't move | Yelp restaurants, Airbnb homes |
| QuadTree | 100% In-Memory RAM | Fast moving vehicles in cities | Uber / Lyft driver dispatch |
| Google S2 | RAM or Database (64-bit int) | Global scale, high speed | Google Maps, Tinder, Pokรฉmon GO |
| PostGIS (R-Tree) | PostgreSQL Disk | Complex borders and polygons | City zoning, delivery fee boundaries |
๐ป 6. Simple Geohash Code (Multi-Language)
Here is how easy it is to convert latitude and longitude into a Geohash string:
// Python 3.10+ Geohash Bisection BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz" def encode_geohash(lat: float, lng: float, precision: int = 6) -> str: lat_range, lng_range = [-90.0, 90.0], [-180.0, 180.0] geohash, is_lng, bit, ch = [], True, 0, 0 while len(geohash) < precision: if is_lng: mid = (lng_range[0] + lng_range[1]) / 2 if lng > mid: ch |= (1 << (4 - bit)); lng_range[0] = mid else: lng_range[1] = mid else: mid = (lat_range[0] + lat_range[1]) / 2 if lat > mid: ch |= (1 << (4 - bit)); lat_range[0] = mid else: lat_range[1] = mid is_lng = not is_lng bit += 1 if bit == 5: geohash.append(BASE32[ch]) bit, ch = 0, 0 return "".join(geohash)
๐งช 7. Interactive Lab: "Find Nearby Pizza" Simulator
Interactive Geohash & 8-Neighbor Simulator
๐ฏ 8. Test Your Understanding
You stand at Geohash "9q8yy". A coffee shop is 50 meters away at Geohash "9q8yw". If the SQL query runs WHERE geohash LIKE '9q8yy%', why does it return 0 results?
Uber receives 1,000,000 driver GPS coordinates every 4 seconds. Why is storing dynamic driver locations in PostGIS with disk R-Trees impractical compared to In-Memory Google S2 / QuadTrees?