应选用point类型——它专为经纬度设计,语义清晰、索引高效、函数支持完整;建表需显式指定srid 4326,插入用st_geomfromtext带srid,查询用st_distance_sphere计算米级距离。

MySQL 8.0 中该用 POINT 还是 GEOMETRY?
直接选 POINT——它专为经纬度坐标设计,语义清晰、索引高效、函数支持完整。用 GEOMETRY 虽然也能存,但会多一层类型判断开销,且 ST_Distance_Sphere() 等地理计算函数在 POINT 上表现更稳定。
建表时明确指定 SRID(空间参考系统):MySQL 8.0 默认要求地理坐标必须带 SRID,WGS84(地球椭球模型)对应 SRID 4326,这是绝大多数 GPS 数据的标准:
CREATE TABLE places ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), location POINT SRID 4326, SPATIAL INDEX(location) );
注意:SPATIAL INDEX 必须配合 POINT 字段且 SRID 一致,否则建索引会失败。
插入和查询地理数据时的常见错误
最常踩的坑是坐标顺序写反:MySQL 的 POINT 要求 POINT(longitude, latitude)(经度在前,纬度在后),和常见 API(如 Google Maps)一致,但和部分 GIS 工具(如 PostGIS 默认 POINT(lat, lon))相反。插错会导致位置偏移几千公里。
插入示例:
INSERT INTO places (name, location) VALUES
('北京南站', ST_GeomFromText('POINT(116.372 39.853)', 4326)),
('上海虹桥', ST_GeomFromText('POINT(121.338 31.199)', 4326));
-
ST_GeomFromText()是安全写法,显式传入 SRID;不要用POINT()构造函数直接拼字符串 - 查询时若需返回可读坐标,用
ST_X(location)和ST_Y(location)提取经/纬度,别用AsText()解析字符串 - WHERE 条件中避免对
location字段用函数(如ST_X(location) > 116),这会让空间索引失效
按距离筛选时为什么 ST_Distance_Sphere() 比 ST_Distance() 更可靠?
ST_Distance() 在 SRID 4326 下默认返回“度”单位的距离(无实际物理意义),而 ST_Distance_Sphere() 才真正按地球曲率计算米级距离,结果可直接用于“5km 内门店”这类业务逻辑。
正确用法(带空间索引加速):
SELECT id, name,
ST_Distance_Sphere(location, ST_GeomFromText('POINT(116.372 39.853)', 4326)) AS distance_m
FROM places
WHERE ST_Distance_Sphere(location, ST_GeomFromText('POINT(116.372 39.853)', 4326))
- WHERE 中重复调用
ST_Distance_Sphere()不影响性能,MySQL 8.0 会自动优化 - 如果要查“某个多边形区域内”的点,用
ST_Contains(poly, location),但 poly 必须也是 SRID 4326 且已建空间索引 - 批量更新坐标时,务必验证新值是否在有效范围内(经度 -180~180,纬度 -90~90),超界会导致
ST_GeomFromText()返回 NULL
升级或迁移旧表时的空间字段兼容性问题
MySQL 5.7 升到 8.0 后,原有 POINT 字段若没设 SRID,会默认变成 SRID 0,此时所有地理函数(ST_Distance_Sphere 等)都会报错 ER_NOT_STRICTLY_INCREASING_SRID。
修复步骤必须严格按顺序执行:
- 先用
ALTER TABLE places MODIFY location POINT SRID 4326;更新列定义(不能只改 SRID) - 再用
UPDATE places SET location = ST_SetSRID(location, 4326) WHERE location IS NOT NULL;补全 SRID - 最后重建空间索引:
ALTER TABLE places DROP INDEX location, ADD SPATIAL INDEX(location);
漏掉任意一步都可能导致查询失败或索引不生效。SRID 是硬约束,不是可选元数据。











