转载自空间索引 - 各数据库空间索引使用报告 - 枕边书
如需个人备份,请阅读原文。
目录
空间索引
我们都用过索引。 它是一种特殊的存储结构,就像图书馆的图书分类存储策略或者现代图书馆的图书查询系统一样,可以帮助我们快速找到我们需要的图书。 在数据库中,索引存储一般采用B树或B+树来实现,利用二分查找的方法快速定位数据位置。
普通索引对于一维数据(key->data)来说是完美的,但是对于空间数据(lon,lat->data)就有些无能为力了。 如果查询 (116.27636, 40.) 附近的点:
这样就需要用到空间索引了。 空间索引是通过四叉树、R树等数据结构以及使用普通B树索引将二维数据转换为一维数据的算法来实现的。 它们都可以实现空间范围内的快速搜索。
不过,今天的话题不在这里。 我们的首要目标是解决问题。 这些空间索引的实现,以后会专门用来写文章。 本文将谈谈现有数据库对空间索引的支持,希望能帮助像我这样的GIS新手做出技术选择。
该小组正在准备切换 POI 数据的存储数据库。 花了一周的时间安装和配置各种数据库来测试空间索引的效率。 我们测试了Redis、Mongo、Mysql等几个支持空间索引的知名数据库。 技术选型工作已基本完成。 ,但是过程中走过的坑和配置经验不能丢。 详情如下所示:
Redis简介
Redis,一个强大且高效的缓存数据库(或许不仅仅是一个缓存数据库),已经成为类似于关系存储数据库的各种项目中不可或缺的组件。 首先考虑它,因为它的效率有保证,项目中几乎是必需的,而且运维成本很低。 Redis的空间索引采用了该原理,并与集合存储相结合,查询效率接近log(N)。
Redis 3.0及以上版本支持空间索引。 新项目不需要考虑这些,而普通老项目可能需要升级Redis。 另外,PHP中的Redis扩展可能需要升级以支持Redis的空间索引功能。
使用
Redis的安装和配置这里就不说了。 这里简单介绍一下Redis的GEO系列功能。
综上所述
Redis确实高效、易用,但是有一个难以克服的问题,那就是无法实现多条件查询。 Redis 非常适合查询附近的点,但如果要求是查询附近的餐馆怎么办? 或者您正在寻找附近的“万达”?
实现这一目标并非不可能:
参考:Redis 命令参考 » GEO(地理位置)
介绍
它是一个支持空间索引的旧数据库。 作为文档数据库,它在存储日志或静态数据时效果很好。 它提供两种类型的空间索引:
2d 索引和索引都是使用 B+ 树的算法来实现的。
使用
Mongo中创建空间索引的方法非常简单:db..( { field : "" } );。
查询语句类似(以下是查询距离目标点3000米以内的位置):
db.poi.find( { loc :
{ $near :
{ $geometry :
{ type : "Point" ,
coordinates : [ 113.965355, 23.782865]
} ,
$maxDistance : 3000
}
}
} )
使用Mongo时需要注意以下几点:
综上所述
Mongo的空间索引比较灵活。 对象包括点、线、多边形、多线段、多个点和多个多边形。 支持包含、交集、相邻查询,同时也解决了Redis的多条件查询问题。
但测试发现mongo存在以下问题:
参考:地理空间索引和查询 ( )
»
介绍
它是著名的关系数据库,其上构建的空间对象扩展模块使其成为真正的大规模空间数据库。 它通过R树或GIST树索引实现共空间索引,查询效率极高。 同时,它很好地支持分词模糊查询,还可以解决按地名查询的需求。
它是一个开源程序,为对象关系数据库存储空间地理数据提供支持,将其转变为能够进行空间数据管理、数量测量和几何拓扑分析的空间数据库。 实现了Open提出的基本要素类(点、线、面、多点、多线、多面等)的SQL实现参考。
使用
与其他数据库相比,它的使用较为繁琐。
需要安装要使用的空间索引。 因为依赖的工具很多且复杂,所以可以先使用yum、apt-get等工具。 数据库完成后,使用命令初始化数据库; 使用非root用户-D启动服务; 使用; 安装扩展; 使用 INDEX ON 表 USING gist(field);;
然后您可以创建表和索引来引导数据。
以下是典型的查询语句(查询目标点3000米以内的位置名称和距离):
SELECT id, name, st_astext(loc),
ST_Distance(loc, ST_GeographyFromText('SRID=4326;POINT(118.08688 33.64843)')) as dist
FROM test WHERE
ST_DWithin(loc, ST_GeographyFromText('SRID=4326;POINT(118.08688 33.64843)'), 3000)
order by dist ASC limit 200;
使用时还要注意:
综上所述
对空间查询的支持非常灵活,可以支持各种复杂的空间查询。 可以计算不同投影坐标系下的真实空间距离,查询效率极高。 当使用大量数据时,性能不会像mongo那样急剧下降。
同时,它的关系数据库特性允许我们执行多条件查询。 最后还可以使用扩展进行中文分词,支持地名的模糊查询。
虽然存在复杂索引时写入速度较慢的问题,但对于存储不经常变化的位置信息来说问题不大。
参考:PgSQL·功能分析·O2O应用中的优势
毫秒级高效实现全表全字段模糊查询
MySQL简介
不言而喻,Mysql的重要和强大。 其存储引擎很早就支持空间索引。 仅在 5.7.4 labs 版本中添加了对空间索引的支持。
它们都通过 R 树实现空间索引。
使用
参考文件:19.6.1。 创建空间索引中文文档
在Mysql中使用空间索引时需要注意以下几点:
下面是一个典型的空间查询语句(查询距离目标点3km以内的点):
SELECT id, ST_Distance_Sphere(Point(-73.951368, 40.716743), geom) as dist, tags, ST_AsText(loc)
FROM nodes
WHERE ST_Contains( ST_MakeEnvelope(
Point((-73.951368+(3/111)), (40.716743+(3/111))),
Point((-73.951368-(3/111)), (40.716743-(3/111)))
), loc )
ORDER BY dist LIMIT 10
综上所述
由于功能比太强大,事务、行锁、B+树索引等功能都是不可替代的,所以这里就不讨论了。
Mysql的空间索引查询效率并不低。 作为传统的关系型数据库,它的多条件支持和分词也得到了很好的支持。
虽然我对空间索引有信心,也有一些期待,但是对于一个已经存在很长时间的系统来说,升级数据库版本确实不是一件简单的事情。
参考:MySQL博客-mysql对GIS空间数据的支持
总结
我用126万个POI数据进行了测试,查询3公里范围内的点(最多200条)。 系统信息:.12(); 核心:2 GHz 英特尔酷睿 i5; 内存:8 GB 1867 MHz;
以下是各个数据库的对比:
数据库耗时区域查询、多条件、分词支持、运维复杂备注
雷迪斯(3.2.8)
1-10毫秒
不支持
不支持
不支持
低的
简单但功能单一
蒙戈(3.4.4)
10-50毫秒
支持
支持
不支持
中间
因此,当数据量较大时,性能会显着下降。
(9.6.2)
3-8毫秒
支持
支持
支持
中间
数据写入速度慢
mysql(5.7.18)
8-15毫秒
支持
支持
支持
低的
版本升级太难
测试运行过程中可能会出现一些错误。 熟练使用这些数据库的人可以评论交流。
没有一个数据库一定是好的,只要适合场景就行。