C++常见空间索引效率对比

第一篇博客,感谢下带我这个门外汉入了GIS行业的导师李治江老师~


由于打算写一个空间数据引擎,在空间索引和属性索引方面搜集了一些开源实现,本文用以对比C++ GIS开发中常见的空间索引实现的效率


测试环境

操作系统 Windows 7 Professional SP1
CPU Inter Core i7-3520M @ 2.9GHz
内存 8GB
系统盘硬盘 SanDisk SDSSDXP120G
数据盘硬盘 HGST HTS725050A7E630
开发环境 Visual Studio 2008 SP1

实验对象

空间筛选的大致流程基本都是:
1. 矩形框初筛,通过待查询矩形框与数据外包矩形相交快速判断
2.对初筛后缩小了的数据集进行相交、包含、相切、相离等精确判断
空间索引就是提高第一步矩形运算效率的算法
其实不管什么实现,矩形相交的快速判断方法是固定的,四个边界数值的比较,除非写汇编、写机器码,否则不太有提升空间。而空间索引的算法优劣,主要在于如何减少无关数据的访问次数
空间数据至少是二维数据,常用的一维索引(如BTree/Bitmap索引等)无法满足需求,常用的空间索引算法有BSP树、K-D-B树、R树、R+树和CELL树(摘自百度百科,补充四叉树)。
本文要对比的是一些常见的C++空间索引开源实现
loop 最原始的循环,每个节点都访问
shapelib-qix shapelib提供的默认空间索引算法,基于四叉树的实现。支持硬盘、内存两种模式
shapelib-sbn 从gdal-1.10起添加的对ArcGIS生成的sbn格式的空间索引支持,笔者将其编译入了最新的shapelib中。仅支持硬盘模式
geos geos提供了若干种空间索引算法,本文对其中的STRTree和QuadTree分别进行了测试。仅支持内存模式
spatialindex 提供了多种基于RTree的空间索引算法,还包括时空GIS所需要的多版本索引算法等。本文仅对二维数据索引,因此仅探讨RTree。支持硬盘、内存两种模式

对比方法

测试数据

郑州市矢量数据
数据类型:Line
数据量:1554304条
x_min:454250.000000
x_max:479750.045600
y_min:3839499.634654
y_max:3862000.032000
空间参考:Xian_1980_3_Degree_GK_CM_114E

对比逻辑

对上述数据的打开数据、创建索引、索引查询范围R内数据n次、相关清理作为一次完整流程,记录索引创建时间、索引内存占用情况、查询时间、查询到数据结果数量作为横向对比参考。重复如上操作t次,取平均值。
其中
R:x_min:465701.923
R:x_max:469994.306
R:y_min:3852567.173
R:y_max:3855717.229
n:100
t:5

对比结果

Method Mode Insert(ms) Memory(MB) Query(ms) QueryCount 说明
Loop-vector Memory 2801.2 77.274219 1523.8 60854 使用std::vector作为数据的存取容器
Loop-list Memory 2856.4 106.534375 1367.2 60854
使用std::list作为数据的存取容器
Loop Disk 0.0 0.000000 264532.0 60854
打开数据逐条IO判断
Qix Memory 3499.8 75.525781 745.8 62240 在内存中创建qix索引查询
Qix Disk 3730.6 0.000000 2010.2 62240 使用硬盘中的qix索引查询
Sbn Disk 0.0 10.158594 898.2 63047 使用硬盘中的sbn索引查询
Geos-STRTree Memory 3100.4 136.578125 2878.8 60854
在内存中创建geos::strtree索引查询
Geos-QuadTree Memory 4194.4 302.792969 383.4 64288 在内存中创建geos::quadtree索引查询
SpatialIndex-RTree Memory 83795.2 72.734375 3087.8 60854
在内存中创建rtree索引查询(原始insert接口)
SpatialIndex-RTree Memory-BulkLoad 13041.0 90.471875 2874.6 60854
在内存中创建rtree索引查询(使用bulkload提升创建速度)
SpatialIndex-RTree Disk-BulkLoad 13348.8 18.336719 4249.6 60854
使用硬盘中的rtree索引查询(使用bulkload提升创建速度)


优缺点对比


优点 缺点
qix 1.索引速度极快
2.支持硬盘、内存两种模式
1.仅支持shp数据(仔细研究下代码应该也能把索引部分跟SHPHandle的耦合解开)
sbn 1.硬盘索引速度极快 1.暂无生成sbn的代码,仅能用作只读索引
2.仅支持shp数据
3.仅支持硬盘模式(不过速度其实已经很快了,是否内存化可能不太重要)
geos 1.内存四叉树索引速度为最快 1.仅支持内存模式(对数据量过大的情况应对性不好)
2.geos源码中存在一处内存释放未决,需要使用者对插入索引树的内存做管理,使用较为不便(建议修改源码)
3.内存占用较大
spatialindex 1.支持硬盘、内存两种模式 1.索引生成较慢(做大数据量的实时编辑数据时可能会有效率问题)

综上考虑,可能会在后续的索引中使用spatialindex

对比缺陷

哎,说到缺陷,还请各位看客多多留下宝贵意见

1.最最百思不得其解的是,除了四叉树的两个索引算法和sbn索引,其他索引居然都比内存生生循环要慢,真是打脸打的厉害啊。。。

  2014-09-10 自圆其说的一种解释

2.对比没有考虑不同数据特点下索引算法的优劣,如数据外包矩形均匀分布或有明显集中是否有影响

3.对不同算法中的可控参数尚未做纵向对比

4.未对比更大数据量的索引稳定性(之前使用过sqlite的rtree,发现超过1000万条记录就会导致索引建立极慢无比,且因为sqlite的rtree实现是通过虚表+关联外键方式实现,实用性较差,因此没有放在此次对比中)


附上源码,敬请指正:

http://pan.baidu.com/s/1kTJttrh


你可能感兴趣的:(ElfGIS,GIS开发)