innodb 是 mysql 5.7+ 中唯一支持真正生效 spatial 索引的存储引擎,myisam 空间索引已失效且不支持事务;innodb 空间查询需满足三条件:几何对象须用 st_geomfromtext 构造、srid 必须一致、必须用 st_intersects 等函数触发索引,st_distance 不走索引。

在 MySQL GIS 开发中,InnoDB 是唯一实际可用、性能可保障的存储引擎——MyISAM 的空间索引在 5.7+ 版本中基本失效,且不支持事务与并发安全,已不可用于生产。
MySQL 5.7+ 中只有 InnoDB 支持真正生效的 SPATIAL 索引
MyISAM 虽然语法上允许 CREATE SPATIAL INDEX,但在 MySQL 5.7 及之后版本中:
• EXPLAIN 显示 type: ALL(全表扫描),优化器无法识别其 R-Tree 索引
• 表级锁导致 GIS 批量导入或实时轨迹写入时严重阻塞读查询
• 缺少事务支持,一次坐标批量更新失败后无法回滚,极易造成空间数据错位或不一致
• 官方手册已将 MyISAM 空间功能明确标记为 legacy,后续补丁不保证兼容
而 InnoDB 在 5.7+ 中原生支持:
• POINT、POLYGON、LINESTRING 列类型 + SPATIAL 索引(R-tree)
• 索引仅允许建在单个非 NULL 的 GEOMETRY 列上
• 必须用 ST_Intersects()、MBRContains() 等函数触发索引,geom = 或 ST_Distance(geom, ...) 不走索引
InnoDB 空间查询必须满足的三个硬性条件
即使建了 SPATIAL 索引,90% 的“没生效”问题都出在写法上:
• 所有参与比较的几何对象必须使用 ST_GeomFromText() 或 ST_PointFromText() 构造,不能直接写 WKT 字符串(如 'POINT(116.4 39.9)')
• 所有几何列和构造对象必须声明相同 SRID(例如都用 SRID 4326),否则报 ER_WRONG_ARGUMENTS 或静默退化为全表扫描
• 查询条件中必须显式调用能触发 R-tree 的函数,例如:
WHERE ST_Intersects(geom, ST_GeomFromText('POLYGON((...))', 4326))
WHERE MBRContains(ST_GeomFromText('POLYGON((...))', 4326), geom)
而不是:
WHERE geom && ST_GeomFromText(...)(&& 在 5.7+ 中对 InnoDB 无效)
高纬度/跨经度场景下,别依赖 ST_Distance() 做范围筛选
ST_Distance() 函数本身不走索引,纯计算开销大,尤其在千万级点表中会直接拖垮查询:
• 错误写法:WHERE ST_Distance(geom, ST_PointFromText('POINT(116.4 39.9)', 4326)) <br>• 正确做法:先用 <code>MBRContains() 或 ST_Within() 做 MBR 粗筛(走索引),再用 ST_Distance_Sphere() 做球面距离精筛(不走索引但数据量已大幅减少)
• 若需高频半径查询,建议预计算四边形边界:WHERE lat BETWEEN ? AND ? AND lng BETWEEN ? AND ?,配合 B-tree 索引作为兜底方案(注意高纬度变形误差)
真正决定 GIS 查询性能的,从来不是“选哪个引擎”,而是你是否严格满足 InnoDB 空间索引的触发前提——漏掉任何一个条件,索引就只是磁盘上一段闲置的 R-tree 结构。











