Работа с геоданными: PostGIS, MySQL Spatial, Geography и Geometry
Почему геоданные — это круто? 🌍
Представь: ты можешь находить все кафе в радиусе 500 метров от офиса, строить оптимальные маршруты доставки или анализировать зоны покрытия сотовой сети. Всё это — геоданные! А теперь давай научимся с ними работать.
PostGIS vs MySQL Spatial: в чём разница?
PostGIS — расширение для PostgreSQL, которое превращает его в мощную гео-СУБД. Поддерживает:
- Все типы геоданных (Point, LineString, Polygon и др.)
- Пространственные индексы (GIST)
- Сотни функций:
ST_Distance,ST_Contains,ST_Intersects
-- Пример в PostGIS
SELECT name
FROM coffee_shops
WHERE ST_DWithin(
location,
ST_MakePoint(37.6178, 55.7512), -- Координаты Кремля
500 -- Радиус в метрах
);
MySQL Spatial — встроенный функционал MySQL, но с ограничениями:
- Нет типа
geography(толькоgeometry) - Меньше функций (но базовые есть)
- Работает в метрической системе (не учитывает сферу Земли)
-- Пример в MySQL
SELECT name
FROM coffee_shops
WHERE ST_Distance_Sphere(
location,
ST_GeomFromText('POINT(37.6178 55.7512)')
) <= 500;
👉 Вывод: PostGIS — для сложных задач, MySQL Spatial — для простых.
Geography vs Geometry: битва типов 🥊
Geometry (плоская система)
- Работает в 2D/3D пространстве
- Быстрые вычисления (евклидова геометрия)
- Идеально для карт небольших территорий
-- Расстояние между двумя точками в Geometry (в градусах!)
SELECT ST_Distance(
ST_GeomFromText('POINT(0 0)'),
ST_GeomFromText('POINT(1 1)')
);
Geography (эллипсоидная система)
- Учитывает кривизну Земли
- Координаты в градусах (WGS84)
- Точнее для глобальных расчетов
-- Расстояние между Москвой и Санкт-Петербургом (в метрах!)
SELECT ST_Distance(
ST_GeographyFromText('POINT(37.6178 55.7512)'), -- Москва
ST_GeographyFromText('POINT(30.3159 59.9391)') -- СПб
);
🔍 Важно: В PostGIS можно использовать оба типа, в MySQL — только Geometry.
Практика: строим геозапросы 🛠️
1. Поиск объектов в радиусе
-- PostGIS: Кафе в 1 км от точки
SELECT name, ST_AsText(location) AS coords
FROM places
WHERE ST_DWithin(
location::geography,
ST_MakePoint(37.6178, 55.7512)::geography,
1000
);
2. Пересечение полигонов
-- MySQL: Найти районы, пересекающиеся с парком
SELECT districts.name
FROM districts, parks
WHERE ST_Intersects(
districts.geom,
parks.geom
)
AND parks.name = 'Центральный парк';
3. Построение маршрута
-- PostGIS: Соединяем точки линией
SELECT ST_MakeLine(
ST_Point(0, 0),
ST_Point(1, 1),
ST_Point(1, 2)
) AS route;
Оптимизация: пространственные индексы 🚀
Без индексов геозапросы тормозят. Решение — GIST (в PostGIS) или SPATIAL (в MySQL):
-- PostGIS
CREATE INDEX idx_places_geo ON places USING GIST(location);
-- MySQL
CREATE SPATIAL INDEX idx_places_geo ON places(location);
💡 Правило: Индексируй поля, по которым часто ищешь (ST_Distance, ST_Contains).
Где применять эти знания? 🗺️
- Логистика: оптимизация маршрутов доставки
- Ритейл: анализ зон покрытия магазинов
- Недвижимость: поиск объектов в нужном районе
- IoT: трекинг устройств с GPS
Попробуй прямо сейчас — создай базу с геоданными и сделай свой первый пространственный запрос! Координаты твоего успеха уже определены. 😉