SpatiaLite

SpatiaLite 使用指南

  SpatiaLite 是一套具有空间数据功能的 SQLite 数据库系统。

  本文简单介绍SpatiaLite ,说明空间索引使用方式,多线程并发下的使用以及常见问题

Contents

SpatiaLite简介

        SpatiaLite是一个用来扩展SQLite的内核的开源库,支持完全成熟的空间SQL功能。
其特点有:

  • 一个实现完整的SQL引擎的轻量级库

  • 标准的SQL执行:几乎完全的SQL-92标准

  • 没有复杂的客户端/服务器结构

  • 整个数据库简单地对应于单个文件,且文件大小没有限制

  • 跨平台

  • 无需安装,无需配置

        Spatialite提供一个完整而强大的空间数据库管理系统(主要是与OGC-SFS兼容),而且由于其跨平台及轻量级的特点,常被用于涉及LBS功能的移动端应用开发中。

空间索引使用

        SpatiaLite使用R*Tree作为空间索引 R*Tree 索引是一个高度平衡的树。它的叶节点存放指向数据的指针。并且   RTree   能够保证对一个空间数据的搜索只需要访问很小一部分的  N ode。
R-Tree特点:

  • SpatiaLite的R*Tree都是一张独特的表(虚表)
  • SpatiaLite自己完全不知道R*Tree和相应的表中几何列的对应关系
  • SpatiaLite实现了几个触发器,以确保R*Tree与几何列保持同步
  • SpatiaLite表中的每一条记录都通过ROWID来标识
  • R*Tree与几何列通过ROWID来关联

  • 如果表包含主键,则ROWID与主键有唯一关联

  • 如果表不包含主键,则ROWID仅仅是相对行号

       使用空间索引前必须要先创建空间索引,空间索引可通过下面的SQL语句来创建:

       select CreateSpatialIndex('table_name', 'column_name')
       如果查询结果返回1,则空间索引创建成果;返回0,则空间索引创建失败

       Spatialite默认不使用空间索引,除非你明确地在查询语句中包含空间索引(这是不同于PostGIS的,其会自动使用空间索引,如果可用)

使用空间索引查询数据可通过如下语句来完成:

SELECT * FROM table_name A  WHERE 

     ST_Within(GeomFromText(ST_AsText(A.geo_column)), GeomFromText('POLYGON((116.37754 39.95149,116.37754 39.95137,116.37891 39.95137,116.37754 39.95149))')) = 1

     AND A.ROWID IN 

               (SELECT ROWID FROMSpatialIndex s WHERE s.f_table_name='table_name 

                AND s.search_frame = GeomFromText('POLYGON((116.37754 39.95149,116.37754 39.95137,116.37891 39.95137,116.37754 39.95149))'))

      其中 ST_Within, GeomFromText,ST_AsText等函数均为Spatialite的内置函数,具体可参考这里

常见问题

  • 空间索引失效
       
下面以一个列子来说明空间索引失效的场景:

       如上图所示,我们创建了一张test表,并插入了几条记录,值得注意的是,这张表没有主键
       接着进行空间查询:

没有意外,我们按预期查出了所需数据。接下来我们删除a、d、e三条记录,并紧缩表

从结果中可以看出,当我们删除记录并回收空间后,查询结果发生错误,查询少了一条记录!
查询记录丢失的原因正是因为:空间索引严重地损坏了
分别执行两个查询:

可以看出,在执行VACUUM语句后,test表的ROWID被重新分配了,但对应的R*Tree却没有改变 主表和 R*Tree的对应关系不再可用
结论:
1)VACUUM操作不会触发主表几何与R*Tree的一致性维护;
2)表如果没有定义主键,则有可能导致空间索引失效;
3)如果表定义了主键,VACUUM操作是非常安全的
因此,强烈不推荐创建没有主键的包含几何的数据表

数据表空间索引的状态是可以检测和恢复的:
检测:

返回0说明空间索引失效,返回1说明索引正常。
恢复:

再次检测:

重新执行查询:

索引已经恢复,数据查询正常