Overpass API 'around'模块运行过慢的优化方案咨询
我正在使用基于OSM的Overpass API的around模块,目标是获取指定坐标一定半径范围内的所有位置。分别用Python和TypeScript进行了测试,以下是TypeScript代码:
async function searchNearbyFeatures(latitude: number, longitude: number, radius: number): Promise<any[]> { const overpassUrl = 'https://overpass-api.de/api/interpreter'; const query = ` [out:json]; ( node(around:${radius},${latitude},${longitude}); way(around:${radius},${latitude},${longitude}); relation(around:${radius},${latitude},${longitude}); ); out center; `; const params = { data: query, }; try { const response = await axios.get(overpassUrl, { params }); if (response.status === 200) { const data = response.data; return data.elements as any[]; } else { console.error('Error occurred:', response.statusText); return []; } } catch (error) { console.error('Error occurred:', error); return []; } }
示例输入:
latitude = 40.71162073116427 longitude = -74.00619658336431 radius = 20 // meters
问题在于该操作有时运行时长超过20秒!我确定未超出使用限制,因为所有测试都是手动进行的(最多15次API调用)。慢响应问题在TypeScript和Python中均存在,因此并非代码问题。曾尝试查看Overpass的源码以直接使用OSM,但实现难度较大,且未找到仅使用OSM的原生实现方式。是否已有现成解决方案,或能否提供解决该速度问题的建议?
优化Overpass查询语句
当前查询一次性获取所有节点、路径、关系,密集区域会返回大量冗余数据,可做以下调整:- 过滤无关元素:如果不需要全类型元素,只保留业务需要的(比如仅查
node);或者添加标签过滤条件,比如只获取带名称的元素(node["name"](around:...);),减少返回数据量。 - 精简输出字段:
out center可替换为out ids tags center;,仅返回ID、标签和中心点,避免传输不必要的元数据;如果不需要中心点,改用out body进一步缩减数据。 - 复用查询参数:虽然Overpass会自动处理重复参数,但可通过变量定义让查询更简洁,减少解析开销:
[out:json]; ( node(around:${radius},${latitude},${longitude}); way(around:${radius},${latitude},${longitude}); relation(around:${radius},${latitude},${longitude}); ); out ids tags center;
- 过滤无关元素:如果不需要全类型元素,只保留业务需要的(比如仅查
切换Overpass公共实例
官方公共实例https://overpass-api.de/api/interpreter高峰时段负载较高,可选择离目标坐标更近的区域化公共实例,降低网络延迟。本地缓存查询结果
对相同坐标和半径的查询,将结果缓存到本地文件或内存中,重复查询时直接读取缓存,完全避免API调用开销。调整查询频率与范围
即使手动调用,短时间内多次查询也可能触发实例的负载限流(并非使用次数限制),可适当增加查询间隔;如果业务允许,可尝试微调半径(比如缩小到15米),减少需要扫描的元素数量。本地部署Overpass实例
如果长期需要高频查询,本地部署Overpass服务器是彻底解决速度问题的方案。下载目标区域的OSM数据切片搭建本地实例,查询速度会大幅提升,完全不受公共实例负载影响。
内容的提问来源于stack exchange,提问作者ArieAI

