java调用GDAL向GeoPackage写入数据慢的解决方法

目录

一、问题描述

二、解决方法

三、代码例子

四、总结 


一、问题描述

GeoPackage(简称“GPKG”)是本地化的轻量地理数据库,在一次使用GDAL函数创建GeoPackage的时候,直接用了原先写过的写Shapefile属性的代码(大致如下),结果发现运行速度非常慢、但如果是用来写Shapefile属性,速度比较快。经过排查最后发现是在调用SetFeature时消耗资源较多,怀疑是其内部是逐条提交的,但不能确认。于是向GDAL官网文档求助。

        Feature feature;while ((feature = oLayer.GetNextFeature()) != null) {		feature.SetField("RVI", 1);oLayer.SetFeature(feature);}

二、解决方法

查了GDAL文档中关于矢量驱动GPKG的参数描述,得知GPKG内部使用SQLite实现,SQLite是支持事务的数据库管理系统(DBMS),在默认情况下,GPKG内部数据更新是逐条提交的,这使得更新速度降低。

又查阅文档得知GDAL在写入矢量时可以使用StartTransaction()、RollbackTransaction()、CommitTransaction()来控制事务,但不是所有矢量驱动都支持事务,比如ESRI Shapefile就不支持。所还需要调用TestCapability()来测试图层使用具有处理事务的能力。

因此,如果想写一个基于GDAL的支持处理事务的数据写入程序,以下思路是一种实现:

1.首先打开驱动、数据源、图层。

2.校验图层存在的情况下,调用TestCapability测试图层是否具备事务处理能力,若具备能力,则StartTransaction打开手动处理事务(类似于JDBC中手动将自动提交关闭)。

3.遍历要素,对其中一个字段进行修改(这里简化了,实际业务应该更加复杂),每2万条调用CommitTransaction提交一次事务,结束遍历时,再提交一次。

4.保存图层、数据源;销毁图层、数据源。

下图是对手动提交事务逻辑的描述: 

以上实现思路中,手动处理事务的方法与JDBC中批量更新数据的方法逻辑上是一样的, 如果常CRUD增删改查的话,就很容易理解。

三、代码例子

以下代码仅供学习交流,不建议直接用于生产环境。相对上述思路,代码中加入了一个是否启用手动处理事务的参数,该参数是用于对比试验,用来对比启用手动处理事务和不启用的耗时差距的。实际使用时,可以不必如此。

核心部分:

        boolean supportTransactions = oLayer.TestCapability("transactions");if (withTransaction && supportTransactions)oLayer.StartTransaction();for (int i = 0; i < featureList.size(); i++) {Feature feature1 = featureList.get(i);feature1.SetField(colName, 1.0);oLayer.SetFeature(feature1);if (withTransaction && supportTransactions && i % 20000 == 0) {oLayer.CommitTransaction();oLayer.StartTransaction();}}if (withTransaction && supportTransactions)oLayer.CommitTransaction();

在启动手动事务处理情况下,以上代码判断了图层是否支持事务,不支持事务的情况下,直接SetFeature应用要素,支持事务的图层将会每执行20000条提交一次修改结果。实际业务中,SetField部分的代码可能更加复杂。

完整代码:

    public static void updateVector(String FileName, String strDriverName, String colName, boolean withTransaction) {System.out.println("---------开始处理更新数据任务!---------");// 注册所有的驱动ogr.RegisterAll();// 加载驱动Driver oDriver = ogr.GetDriverByName(strDriverName);if (oDriver == null) {System.out.format("打开驱动失败!gdal错误:%s\n", gdal.GetLastErrorMsg());return;}// 打开文件,获取数据源DataSource oDS = oDriver.Open(FileName, 1);if (oDS == null) {System.out.printf("打开矢量文件%s失败!\n", gdal.GetLastErrorMsg());return;}//打开图层,一般ESRI Shapefile只有一个图层Layer oLayer = oDS.GetLayer(0);if (oLayer == null) {System.out.print("打开图层失败!\n");return;}System.out.println("图层:" + oLayer.GetName());int ct = (int) oLayer.GetFeatureCount();System.out.println("图层要素数量:" + ct);//遍历要素,一个要素可以理解为Shapefile属性表中的一行List<Feature> featureList = new ArrayList<>();Feature feature;while ((feature = oLayer.GetNextFeature()) != null) {featureList.add(feature);}System.out.println("读取图层要素到集合成功!");long start = System.currentTimeMillis();System.out.println("开始更新属性表!");//有些矢量驱动不支持事务boolean supportTransactions = oLayer.TestCapability("transactions");System.out.format("图层是否支持事务:%s,用户是否想启用手动处理事务:%s\n", supportTransactions, withTransaction);if (withTransaction && supportTransactions)oLayer.StartTransaction();for (int i = 0; i < featureList.size(); i++) {Feature feature1 = featureList.get(i);feature1.SetField(colName, 1.0);oLayer.SetFeature(feature1);if (withTransaction && supportTransactions && i % 20000 == 0) {oLayer.CommitTransaction();oLayer.StartTransaction();}}if (withTransaction && supportTransactions)oLayer.CommitTransaction();long end = System.currentTimeMillis();System.out.printf("更新完成,耗时%.3f秒\n", (end - start) / 1000.0);//将图层数据保存到硬盘oLayer.SyncToDisk();oDS.SyncToDisk();System.out.println("保存成功!");oLayer.delete();oDS.delete();System.out.println("---------处理更新数据任务成功!---------");}

调用代码:

    public static void main(String[] args) {String FileName = "E:\\性能测试\\grid1.gpkg";String strDriverName = "GPKG";updateVector(FileName, strDriverName, "RVI", false);updateVector(FileName, strDriverName, "RVI", true);}

在这里,一共调用修改属性的方法两次,第一次不启用手动事务处理,gdal会逐行提交修改内容,第二次启用了手动事务处理,gdal会每修改20000次,提交一次事务,结束时再提交一次。 

 运行结果:

可以发现启用手动处理事务后,写入属性的速度相对没有自动提交事务时大大提高了。 

四、总结 

使用java调用GDAL库来向矢量文件写入数据时,部分矢量驱动不支持事务,可以直接应用到图层,不影响写入效率,部分矢量驱动如GPKG、SQLite等支持事务,并需要手动提交事务才能提高效率。在写矢量数据时,通过判断图层是否支持事务,来决定是否手动提交事务,对提高写入效率有较大帮助。本文经过改进后的程序应该是更加优化后的修改矢量数据的通用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/177526.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 Amazon EKS 搭建开源向量数据库 Milvus

一、前言 生成式 AI&#xff08;Generative AI&#xff09;的火爆引发了广泛的关注&#xff0c;也彻底点燃了向量数据库&#xff08;Vector Database&#xff09;市场&#xff0c;众多的向量数据库产品开始真正出圈&#xff0c;走进大众的视野。 根据 IDC 的预测&#xff0c;…

自定义windows右键菜单,软件卸载后 右键菜单残留 打开方式残留 解决方法

问题&#xff1a; 更改windows右键菜单软件卸载残留&#xff0c;其仍然出现在文件的打开方式列表&#xff0c;右键菜单中。 解决方法1&#xff1a;推荐使用registry workshop批量搜索删除注册表 绿色版&#xff1a; 蓝奏云&#xff1a;https://wwzd.lanzouw.com/iPJNp1em339…

[LeetCode]-225. 用队列实现栈-232. 用栈实现队列

目录 225. 用队列实现栈 题目 思路 代码 232. 用栈实现队列 题目 思路 代码 225. 用队列实现栈 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/implement-stack-using-queues/description/ 题目 请你仅使用两个队列实现一个后…

【Flink】Flink任务缺失Jobmanager日志的问题排查

Flink任务缺失Jobmanager日志的问题排查 问题不是大问题&#xff0c;不是什么代码级别的高深问题&#xff0c;也没有影响任务运行&#xff0c;纯粹因为人员粗心导致&#xff0c;记录一下排查的过程。 问题描述 一个生产环境的奇怪问题&#xff0c;环境是flink1.15.0 on yarn…

人工智能赋能职业教育:技术融合引领教育变革

人工智能赋能职业教育&#xff1a;技术融合引领教育变革 摘要&#xff1a;本文探讨了人工智能技术在职业教育领域的应用及其带来的变革。通过分析人工智能在个性化教学、智能评估和教学资源优化等方面的技术优势&#xff0c;结合职业教育的现状和发展需求&#xff0c;提出了人…

测试员练就什么本领可以让自己狂揽10个offer

最近&#xff0c;以前的一个小徒弟又双叒叕跳槽了&#xff0c;也记不清他这是第几次跳槽了&#xff0c;不过从他开始做软件测试开始到现在已经有2-3年的工作经验了&#xff0c;从一开始的工资8K到现在的工资17K&#xff0c;不仅经验上积累的很多&#xff0c;财富上也实现了翻倍…

需求工程咨询和实施服务

服务概述 多年来经纬恒润在汽车电子产品开发与量产、工程服务、研发流程体系建设方面积累了大量的实际研发经验&#xff0c;并为国内外主流OEM和核心供应商提供了相应的量产产品和研发服务&#xff0c;覆盖车身和舒适域、智能驾驶、智能网联、智能座舱、底盘控制、新能源及动力…

什么是OV SSL证书?

OV SSL证书是一种通过对企业或组织身份进行验证后颁发的SSL证书。与DV&#xff08;域名验证&#xff09;证书相比&#xff0c;OV证书更进一步验证了申请者的真实身份&#xff0c;包括其组织信息。这一验证过程有助于确保用户在与网站或应用程序进行通信时&#xff0c;能够信任其…

【FPGA】十进制计数器 | 实现 4-bit 2421 十进制计数器 | 有限状态机(FSM)

目录 Ⅰ. 实践说明 0x00 十进制计数器 0x01 有限状态机&#xff08;FSM&#xff09; Ⅱ. 实践部分 0x00 4-bit 2421 十进制计数器 Ⅰ. 实践说明 0x00 十进制计数器 十进制计数器是一种以十进制运算的计数器&#xff0c;从 0 数到 9&#xff0c;然后返回 0 状态。由于它需…

从3大维度9个细节聊一聊,边缘计算盒子如何选型

人工智能的蓬勃发展&#xff0c;物联网设备的部署和5G无线技术的到来&#xff0c;越来越多的新兴场景对智能化应用提出了低时延、低带宽、本地化、高安全、低成本的处理需求&#xff0c;包括智慧城市、智慧金融、智慧校园等领域&#xff0c;以及智慧交通、智慧工厂、智慧医疗等…

centos下安装mysql8版本

1、如果服务器没有wget&#xff0c;先下载wget工具 sudo yum install wget 2、下载指定mysql版本的tar包 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.21-1.el7.x86_64.rpm-bundle.tar 3、解压tar包 sudo tar -xvf mysql-8.0.21-1.el7.x86_64.rpm…

大模型的全面回顾,看透大模型 | A Comprehensive Overview of Large Language Models

大模型的全面回顾&#xff1a;A Comprehensive Overview of Large Language Models 返回论文和资料目录 论文地址 1.导读 相比今年4月的中国人民大学发表的大模型综述&#xff0c;这篇综述角度更侧重于大模型的实现&#xff0c;更加硬核&#xff0c;更适合深入了解大模型的一…