常见、免费 GIS/Geo-Databases(PostgreSQL/PostGIS、SQLite/SpatiaLite、H2/H2GIS、...)的功能完整性比较
Functional Completeness Comparison of common, free GIS/Geo-Databases (PostgreSQL/PostGIS, SQLite/SpatiaLite, H2/H2GIS, ...)
对于 GIS 功能的实现,我们必须在各种备选方案之间进行选择。
应避免支付许可费用,因此我们将其缩小为上述 3 种。但也许有人 should/could 也会考虑其他人?
我们的主要标准是:
- 无许可费用
- 最好不限制整个系统的使用(对于 public、政府组织、adjustments/development)
- (XML) xx GB 范围内的输入数据(低冗余)
- (XML) xx GB 范围内的输出(低冗余)(转换后的输入数据)
- 良好的性能(RAM 使用率、CPU 使用率、磁盘使用率)和吞吐量
- SFA-SQL(OGC 标准)
- (问题的重点)
- 需要兼容性但并非绝对必要
- 不需要高功能覆盖率,但需要(至少 "basic" 操作)
- (其他搜索标签:SFS、SFSQL、简单特征访问)
- DB-GIS和sysadm/dbadm用户经验:应该能够安装和配置DB系统
- 开发人员的 DB-GIS 经验:大部分经验 PostgreSQL/PostGIS,其他经验较少
从各个站点收集关于上述几点的重要信息并不容易,所以我会尽量总结(稍后添加)。
到目前为止我们的发现(欢迎 adjust/add):
空间数据库或比较列表
- Wikipedia (2018-10-09)
中的列表相当不完整
- How does PostGIS compare to Spatialite? (2012)
- djangoproject compatibility tables(web 开发框架)比较 PostGIS、Oracle、MySQL、SpatiaLite 和 PGRaster (2018-10-09 / v2.1.2 (2018-10-01))
- 14 alternativeto.net systems (2018-10-09)
(1): 下面的纯 "function names amount" 计算不应被视为完全合格的衡量标准,因为签名设计(重载、可组合性......)可以对实际的灵活性和功能覆盖面有更大的影响。 (=> less 函数理论上可以是 "better")
SQLite with SpatiaLite
- 嵌入式数据库
- 写在C
- ~440(1) geo functions (2018-10-09 / 4.3.0)
- 见底部的计算函数
- SFA-SQL-覆盖率:
H2 with H2GIS
- 嵌入式数据库
- 写在Java
- ~191(1) geo functions (2018-10-09 / 1.4.0)
- SFA-SQL-覆盖率:
H2GIS implements the SQL routines describe in "OpenGIS ® Implementation Standard for Geographic information - Simple feature access - Part 2: SQL option" OGS (2018-10-09 / 06-104r4 )
PostgreSQL with PostGIS
- 普通客户端-服务器数据库
- ~310(1) geo functions (2018-10-09 / 2.5)
- 见底部的计算函数
- SFA-SQL-覆盖率:
我们的preference/choice
(这是非常主观的,仅供参考!)
我们决定使用 PostGIS 只是因为
- 我们认为性能和海量数据处理方面的风险对我们的需求来说是最低的
- 我们将来可能会使用其他常用或更高级的关系数据库功能
- 我们对此有很多经验
- 我们在预安装的 VM 中运送整个系统,因此此时 DBMS 的可嵌入性对我们或客户来说并不重要
附录:计算地理函数的辅助函数
(Java基于脚本 on/tested 带 Firefox 控制台)
JavaSpatiaLite functions site
上的函数计数脚本
结果:
"-#19 version (tr#0 - tr#21)
-#15 generic (tr#21 - tr#38)
-#08 global (tr#38 - tr#48)
-#26 math (tr#48 - tr#76)
+#06 error (tr#76 - tr#84)
+#20 length_cvt (tr#84 - tr#106)
+#02 dms_cvt (tr#106 - tr#110)
-#14 blob (tr#110 - tr#126)
+#32 p0 (tr#126 - tr#160)
+#11 p1 (tr#160 - tr#173)
+#11 p2 (tr#173 - tr#186)
+#03 p3 (tr#186 - tr#191)
+#13 p3misc (tr#191 - tr#206)
+#20 p4 (tr#206 - tr#228)
+#01 repair (tr#228 - tr#231)
+#02 compress (tr#231 - tr#235)
+#09 cast (tr#235 - tr#246)
+#04 dims-cast (tr#246 - tr#252)
+#04 p5 (tr#252 - tr#258)
+#14 p6 (tr#258 - tr#274)
+#07 p7 (tr#274 - tr#283)
+#03 p8 (tr#283 - tr#288)
+#03 p9 (tr#288 - tr#293)
+#02 p10 (tr#293 - tr#297)
+#08 p11 (tr#297 - tr#307)
+#11 p12 (tr#307 - tr#320)
+#03 p13 (tr#320 - tr#325)
+#08 p14 (tr#325 - tr#335)
+#28 p14b (tr#335 - tr#365)
+#03 p14c (tr#365 - tr#370)
+#16 p14d (tr#370 - tr#388)
+#10 p15 (tr#388 - tr#400)
+#23 p15plus (tr#400 - tr#425)
+#22 p16 (tr#425 - tr#449)
-#02 p16metacatalog (tr#449 - tr#453)
+#41 p16style (tr#453 - tr#496)
-#03 p16isometa (tr#496 - tr#501)
+#07 p16fdo (tr#501 - tr#510)
+#23 p16gpkg (tr#510 - tr#535)
+#04 p17 (tr#535 - tr#541)
+#04 p18 (tr#541 - tr#547)
+#33 xmlBlob (tr#547 - tr#582)
+#12 srid (tr#582 - tr#596)
+#17 advanced (tr#596 - tr#615)
gis functions: 440"
函数:
x=$x("//tr/td/h3/a[@name]") // header anchors
os='' // output string
trs=$x("//tr") // tr nodes
gf=0 // gis functions
nongis= ['version','generic','global','math','blob','p16metacatalog','p16isometa'] // non-gis function sections/anchors
for (var i=0; i< x.length; i++ ) {
isgs = nongis.indexOf( x[i].attributes['name'].value ) == -1 // is gis section
c= trs.indexOf( x[i].parentNode.parentNode.parentNode ) // current header index
n= (i == x.length-1) ? trs.length+1 : trs.indexOf( x[i+1].parentNode.parentNode.parentNode ) // next header index
os+= (!isgs ? '-' : '+' ) + '#' + ((n-c-2 > 9 ? '' : '0') + (n-c-2)) + ' ' + x[i].attributes['name'].value + ' (tr#' + c + ' - tr#' + n + ')\n'
gf+= isgs ? n-c-2 : 0
}
os += 'gis functions: ' + gf
JavaPostGIS functions site
上的函数计数脚本
$x('//a[@name="PostGIS_TypeFunctionMatrix"]/../../../../..//tbody/tr').length
对于 GIS 功能的实现,我们必须在各种备选方案之间进行选择。 应避免支付许可费用,因此我们将其缩小为上述 3 种。但也许有人 should/could 也会考虑其他人?
我们的主要标准是:
- 无许可费用
- 最好不限制整个系统的使用(对于 public、政府组织、adjustments/development)
- (XML) xx GB 范围内的输入数据(低冗余)
- (XML) xx GB 范围内的输出(低冗余)(转换后的输入数据)
- 良好的性能(RAM 使用率、CPU 使用率、磁盘使用率)和吞吐量
- SFA-SQL(OGC 标准)
- (问题的重点)
- 需要兼容性但并非绝对必要
- 不需要高功能覆盖率,但需要(至少 "basic" 操作)
- (其他搜索标签:SFS、SFSQL、简单特征访问)
- DB-GIS和sysadm/dbadm用户经验:应该能够安装和配置DB系统
- 开发人员的 DB-GIS 经验:大部分经验 PostgreSQL/PostGIS,其他经验较少
从各个站点收集关于上述几点的重要信息并不容易,所以我会尽量总结(稍后添加)。
到目前为止我们的发现(欢迎 adjust/add):
空间数据库或比较列表
- Wikipedia (2018-10-09) 中的列表相当不完整
- How does PostGIS compare to Spatialite? (2012)
- djangoproject compatibility tables(web 开发框架)比较 PostGIS、Oracle、MySQL、SpatiaLite 和 PGRaster (2018-10-09 / v2.1.2 (2018-10-01))
- 14 alternativeto.net systems (2018-10-09)
(1): 下面的纯 "function names amount" 计算不应被视为完全合格的衡量标准,因为签名设计(重载、可组合性......)可以对实际的灵活性和功能覆盖面有更大的影响。 (=> less 函数理论上可以是 "better")
SQLite with SpatiaLite
- 嵌入式数据库
- 写在C
- ~440(1) geo functions (2018-10-09 / 4.3.0)
- 见底部的计算函数
- SFA-SQL-覆盖率:
H2 with H2GIS
- 嵌入式数据库
- 写在Java
- ~191(1) geo functions (2018-10-09 / 1.4.0)
- SFA-SQL-覆盖率:
H2GIS implements the SQL routines describe in "OpenGIS ® Implementation Standard for Geographic information - Simple feature access - Part 2: SQL option" OGS (2018-10-09 / 06-104r4 )
PostgreSQL with PostGIS
- 普通客户端-服务器数据库
- ~310(1) geo functions (2018-10-09 / 2.5)
- 见底部的计算函数
- SFA-SQL-覆盖率:
我们的preference/choice
(这是非常主观的,仅供参考!)
我们决定使用 PostGIS 只是因为
- 我们认为性能和海量数据处理方面的风险对我们的需求来说是最低的
- 我们将来可能会使用其他常用或更高级的关系数据库功能
- 我们对此有很多经验
- 我们在预安装的 VM 中运送整个系统,因此此时 DBMS 的可嵌入性对我们或客户来说并不重要
附录:计算地理函数的辅助函数
(Java基于脚本 on/tested 带 Firefox 控制台)
JavaSpatiaLite functions site
上的函数计数脚本结果:
"-#19 version (tr#0 - tr#21)
-#15 generic (tr#21 - tr#38)
-#08 global (tr#38 - tr#48)
-#26 math (tr#48 - tr#76)
+#06 error (tr#76 - tr#84)
+#20 length_cvt (tr#84 - tr#106)
+#02 dms_cvt (tr#106 - tr#110)
-#14 blob (tr#110 - tr#126)
+#32 p0 (tr#126 - tr#160)
+#11 p1 (tr#160 - tr#173)
+#11 p2 (tr#173 - tr#186)
+#03 p3 (tr#186 - tr#191)
+#13 p3misc (tr#191 - tr#206)
+#20 p4 (tr#206 - tr#228)
+#01 repair (tr#228 - tr#231)
+#02 compress (tr#231 - tr#235)
+#09 cast (tr#235 - tr#246)
+#04 dims-cast (tr#246 - tr#252)
+#04 p5 (tr#252 - tr#258)
+#14 p6 (tr#258 - tr#274)
+#07 p7 (tr#274 - tr#283)
+#03 p8 (tr#283 - tr#288)
+#03 p9 (tr#288 - tr#293)
+#02 p10 (tr#293 - tr#297)
+#08 p11 (tr#297 - tr#307)
+#11 p12 (tr#307 - tr#320)
+#03 p13 (tr#320 - tr#325)
+#08 p14 (tr#325 - tr#335)
+#28 p14b (tr#335 - tr#365)
+#03 p14c (tr#365 - tr#370)
+#16 p14d (tr#370 - tr#388)
+#10 p15 (tr#388 - tr#400)
+#23 p15plus (tr#400 - tr#425)
+#22 p16 (tr#425 - tr#449)
-#02 p16metacatalog (tr#449 - tr#453)
+#41 p16style (tr#453 - tr#496)
-#03 p16isometa (tr#496 - tr#501)
+#07 p16fdo (tr#501 - tr#510)
+#23 p16gpkg (tr#510 - tr#535)
+#04 p17 (tr#535 - tr#541)
+#04 p18 (tr#541 - tr#547)
+#33 xmlBlob (tr#547 - tr#582)
+#12 srid (tr#582 - tr#596)
+#17 advanced (tr#596 - tr#615)
gis functions: 440"
函数:
x=$x("//tr/td/h3/a[@name]") // header anchors
os='' // output string
trs=$x("//tr") // tr nodes
gf=0 // gis functions
nongis= ['version','generic','global','math','blob','p16metacatalog','p16isometa'] // non-gis function sections/anchors
for (var i=0; i< x.length; i++ ) {
isgs = nongis.indexOf( x[i].attributes['name'].value ) == -1 // is gis section
c= trs.indexOf( x[i].parentNode.parentNode.parentNode ) // current header index
n= (i == x.length-1) ? trs.length+1 : trs.indexOf( x[i+1].parentNode.parentNode.parentNode ) // next header index
os+= (!isgs ? '-' : '+' ) + '#' + ((n-c-2 > 9 ? '' : '0') + (n-c-2)) + ' ' + x[i].attributes['name'].value + ' (tr#' + c + ' - tr#' + n + ')\n'
gf+= isgs ? n-c-2 : 0
}
os += 'gis functions: ' + gf
JavaPostGIS functions site
上的函数计数脚本$x('//a[@name="PostGIS_TypeFunctionMatrix"]/../../../../..//tbody/tr').length