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

news2024/11/17 22:44:52

目录

一、问题描述

二、解决方法

三、代码例子

四、总结 


一、问题描述

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.coloradmin.cn/o/1211192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业云盘:作用和特点全解析

一、什么是企业云盘&#xff1f; 企业云盘是基于云计算理念推出的企业数据网络存储和管理解决方案&#xff0c;利用互联网后台数据中心的海量计算和存储能力为企业提供数据汇总分发、存储备份和管理等服务。 简单来讲&#xff0c;企业云盘其实就是企业网盘&#xff0c;是一种为…

那些让我苦笑不得的 Bug:编码之路的坎坷经历

文章目录 1. CSS 中的样式“消失”问题2. JavaScript 的变量命名引发的混乱3. 时间格式的困扰4. 数据库查询条件引发的错误结语 &#x1f389;欢迎来到Java学习路线专栏~那些让我苦笑不得的 Bug&#xff1a;编码之路的坎坷经历 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨…

十大适合外贸企业邮箱的Gmail替代品推荐

电子邮件仍然是许多人选择的媒介&#xff0c;因为它是交换信息的最可靠和正式的方法。无论是个人还是小型企业&#xff0c;电子邮件仍然是个人和专业用途的重要通信工具。它提供了一种安全、可靠且正式的方法来交换信息和文档以及共享文件。 对于大多数人来说&#xff0c;Googl…

Vue中的watch的使用

先看下Vue运行机制图 那么我们思考一件事&#xff0c;vue是通过watcher监听数据的变化然后给发布-订阅&#xff0c;这样实现了dom的渲染&#xff0c;那么我们思考一件事&#xff0c;我们往往需要知道一个数据的变化然后给页面相应的渲染&#xff0c;那么我们工作中在组件中的数…

python安装pip install报错Could not fetch URL https://pypi.org/simple/pip/...更换镜像源

更换镜像源 一. 现象pycharm使用 pip install xxx安装包时&#xff0c;一直报错&#xff1a; 二. 原因&#xff1a;三. 解决办法&#xff1a;一. 临时使用二. 永久更改三. 永久更改1. Windowswindows环境下Windows&#xff08;示例win10&#xff09; 2. Linux or Mac3. Pycharm…

下一代VPN工具:体验TailScale的简便和高效

目录 一、概要VPN 是什么&#xff1f;TailScale 是什么 二、使用1、注册2、下载安装3、 Windows4、Linux5、 Android6、测试 三、Nginx整合Tailscale做端口转发 一、概要 VPN 是什么&#xff1f; 看到 VPN 第一反应应该是翻墙&#xff0c;但 VPN 最初应该也是最普遍的用途应该…

亚马逊鲲鹏系统可全自动化批量操作亚马逊买家号

亚马逊鲲鹏系统可以注册买家号、智能养号、自动下单、自动留评、QA等&#xff0c;是一款从注册到下单于一体的软件。 如果想要自动化注册&#xff0c;那么准备好账号所需要的邮箱、ip、手机号之后就可以进行自动注册了&#xff0c;注册时可以自动输入账号密码信息、自动接收验证…

spring cloud alibaba 之哨兵(sentinel)

sentinel (哨兵) 简介 # 官网 - https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html#_spring_cloud_alibaba_sentinel # github - https://github.com/alibaba/Sentinel/wiki# 简介 - 随着微服务的普及&#xff0c;服务调用的稳定性变得越来…

HPC 工作负载管理 —— IBM Spectrum LSF Suite

全面的工作负载管理解决方案&#xff0c;通过增强用户和管理员体验以及实现规模性能来简化 HPC。 IBM Spectrum LSF Suites 是面向分布式高性能计算 (HPC) 的工作负载管理平台和作业调度程序。基于 Terraform 的自动化现已可用&#xff0c;该功能可在 IBM Cloud 上为基于 IBM …

2023年亚太杯APMCM数学建模大赛数据分析题MySQL的使用

2023年亚太杯APMCM数学建模大赛 以2022年C题全球变暖数据为例 数据分析&#xff1a; 以2022年亚太杯数学建模C题为例&#xff0c;首先在navicat建数据库然后右键“表”&#xff0c;单击“导入向导”&#xff0c;选择对应的数据格式及字符集进行数据导入 导入之后&#xff0c…

录音频用什么软件?助你轻松捕捉声音!

“有没有什么录音频的软件推荐呀&#xff1f;学校要求拍摄一个关于交通安全的纪录片&#xff0c;现在视频拍摄好了&#xff0c;音频却出了问题&#xff0c;需要重新补录声音&#xff0c;但是找不到合适的录音频软件&#xff0c;有人知道吗&#xff1f;” 录制音频是我们在工作…

冯诺依曼体系和操作系统简单介绍

冯诺依曼体系和操作系统简单介绍 冯诺依曼体系 输入设备&#xff1a;键盘&#xff0c;话筒&#xff0c;摄像头&#xff0c;usb&#xff0c;鼠标&#xff0c;磁盘/ssd&#xff0c;网卡等等输出设备&#xff1a;显示器&#xff0c;喇叭&#xff0c;打印机&#xff0c;磁盘&#…

xstream实现xml和java bean 互相转换

目录 pom引用java bean 类XML 转换工具类测试类执行结果注意问题 JAXB方式见&#xff1a; JAXB实现XML和Bean相互转换 Java中实现XML和Bean的转换的方式或插件有以下几种&#xff1a; JAXB&#xff08;Java Architecture for XML Binding&#xff09;&#xff1a;JAXB是Java …

优化了

v2.0.2版本在 github 发布了。 ## 优化的功能 优化(定时任务): 测试计划与定时任务模块进行了合并&#xff0c;极大的简化了操作步聚。 1、前端页面&#xff0c;测试计划plan&#xff0c;加入1个接口&#xff0c;设置每分钟运行1次。 2、开启定时任务服务&#xff0c;后台日志 …

微信小程序H5 uniapp

最近微信小程序对有视频播放的审核严&#xff0c;需要提供“文娱类资质”。而申请这个资质比较繁琐。所以我们在小程序上用web-view做跳转到H5&#xff0c;H5使用uniapp编写。这是小程序关于web-view文档说明。https://developers.weixin.qq.com/miniprogram/dev/component/web…

NI MIMO原型验证系统硬件介绍 已更新 2023年1月6日

https://www.ni.com/zh-cn/shop/wireless-design-test/what-is-the-mimo-prototyping-system/introduction-to-the-ni-mimo-prototyping-system-hardware.html 概览 随着采用无线连接方式的设备大量涌现&#xff0c;迫切需要研发可满足更高数据与容量需求的无线技术。来势汹汹…

抖音直播招聘报白企业人力资源有招聘需求的看过来

人力资源行业抖音招聘报白开始了&#xff0c;但是目前的市面的价格不一&#xff0c;很多人力资源公司最近想做抖音的直播报白&#xff0c;做直播待岗&#xff0c;因为最近刚好是招聘高峰期啊&#xff0c;企业需求大&#xff0c;赶上这一波&#xff0c;但是对目前市面上做抖音报…

力扣每日一题-K个元素的最大和-2023.11.15

力扣每日一题&#xff1a;K个元素的最大和 题目链接:2656.K个元素的最大和 题目描述 代码思路 题目看完直接笑嘻了&#xff0c;还有这么容易的题。由题可知&#xff0c;第一次要找出最大值m&#xff0c;那由于把m1放回去&#xff0c;那第二次找的就是m1&#xff0c;以此类推…

seatunnel及web安装常见问题与解决方法

mvn加速下载seatunnel相关jar包 安装seatunnel过程中&#xff0c;解压文件后官方默认提供的connector的jar包只有2个&#xff0c;要想连接mysql&#xff0c;oracle&#xff0c;SqlServer&#xff0c;hive&#xff0c;kafka&#xff0c;clickhouse&#xff0c;doris等时&#x…

问题 H: 棋盘游戏(二分图变式)

题意&#xff1a;要求找到 不放车就无法达到最大数的点 的个数 题解&#xff1a;1.以行列绘制二分图 2.先算出最大二分匹配数 3.依次遍历所有边 删除该边&#xff0c;并计算二分匹配最大值 &#xff08;若小于原最大值即为重要点&#xff09;&#xff0…