前言
矢量数据与栅格数据是最为普遍的空间数据类型,在多个领域的GIS类应用中都有大范围使用。Ganos具备完整矢栅数据处理能力,依托阿里云云原生数据库的弹性并行能力,计算效率相较于传统方案有数倍甚至数十倍提升,目前已经在资源管理、交通物流、城市治理、应急处置等多个领域的客户实践中得到了广泛肯定。
由于Ganos依托云原生数据库,相较于自行安装在本地电脑上的传统单机版数据库而言,它的使用方法有些不同,因此在我们发布了一系列的最佳实践文章后,收到了很多用户反馈,一部分用户对于Ganos高效的栅矢数据处理方法很感兴趣,但在数据入库时出现了一些困惑。本次我们专门出一篇解读文章,帮助大家更好的理解如何采用云原生的相关工具进行数据导入操作。
Ganos矢栅数据入库方法
Ganos与PostGIS矢栅数据入库方法区别
使用过社区版Postgresql中PostGIS组件的用户都了解,PostGIS提供了shp2pgsql和raster2pgsql两个命令行工具,帮助用户快速导入矢栅数据。工具需要用户自行指定导入数据的SRID、文件编码、表名、导入方式等信息,栅格工具还需要增加栅格波段、切片大小等信息才可以实现数据导入。这样的方式对于PolarDB这样的云原生数据库并不适用,主要原因为:
- PostGIS提供的导入工具需要用户对于数据库所部署的服务器有完全的掌控,数据需要尽可能上传至服务器的本地磁盘;而云原生数据库PolarDB为共享存储架构,无本地磁盘的概念,同时云原生会考虑底层服务器资源的弹性能力,用户并不清楚数据库所在宿主机的相关信息;
- PostGIS Raster与Ganos Raster在存储结构上存在显著的不同,相关对比信息请参考文章《基于Ganos的栅格引擎开展区域面雨量分析》
因此,从云原生架构的角度出发,Ganos依托云原生对象存储OSS,提供更为便捷的函数级入库工具,支持矢量、栅格数据的快速写入。
Ganos矢栅数据入库方法介绍
矢量数据入库
1. GIS桌面工具导入
由于Ganos所承载的阿里云PolarDB数据库100%兼容PostgreSQL,因此可以使用类似于QGIS这样的GIS桌面工具,通过创建PG数据连接源的方式建立与PolarDB数据的连接,之后采用桌面工具自带的数据导入功能完成数据入库。QGIS连接PG数据的方法网格上的介绍案例非常丰富,此处不再赘述。
2. 基于FDW导入
Ganos推荐使用FDW的方式导入矢量数据。外部数据包装器FDW(FOREIGN DATA WRAPPER)是PostgreSQL提供用于访问外部数据的插件,外部数据源包括本实例中其它库中的数据或其他实例的数据。Ganos FDW提供了对于多种空间数据类型的统一访问,会自动将几何空间数据类型映射为Geometry字段类型,从而允许与数据库内部表进行统一地访问与查询。
比如我们可以把存储在OSS上的poly.shp文件导入到Ganos作为一张带有geometry字段类型的数据表使用,具体流程如下:
首先创建相关扩展:
CREATE EXTENSION ganos_spatialref;CREATE EXTENSION ganos_geometry;CREATE EXTENSION ganos_fdw;
然后通过ST_RegForeignTables方法(参考手册)将空间数据文件poly.shp注册为外表:
SELECT ST_RegForeignTables('OSS://<ak_id>:<ak_secret>@<endpoint>/path/poly.shp');
注册成功后,可以通过information_schema.foreign_tables视图查询到我们刚刚注册的FDW表(poly):
SELECT foreign_table_name FROM information_schema.foreign_tablesORDERBY foreign_table_name ASC;
注意,注册为外表只是通过映射的方式看到具体内容,具体数据并未真正写入数据库中,所以还需要使用如下命令创建数据库表并插入数据:
CREATETABLE poly_db ASSELECT*FROM poly;
栅格数据入库
Ganos提供了两个将外部栅格数据源导入数据库的函数,他们分别是:ST_ImportFrom(参考手册)和ST_CreateRast(参考手册)。他们的功能都是从外部栅格数据创建raster类型对象用于保存影像数据的元信息。但是区别在于ST_ImportFrom会将数据分成若干规则大小(默认为256x256像素)的数据块chunk存储在数据库中(具体位置通过chunkTableName参数指定),而ST_CreateRast只创建一个raster对象,并不会将具体像素信息导入到数据库中。
1. Tiff数据入库
Tiff数据为目前最常见的栅格数据格式之一,下面我们通过具体案例来展示如何从OSS导入Tiff数据到Ganos中。假设我们在OSS存在一景tiff影像,其路径为:
oss://mybucket/data/G50E009001DOM.tif
首先,我们需要创建一个包含有raster字段类型的表来保存:
CREATETABLE raster_table ( id integer, format text, rast raster );
然后我们分别通过ST_ImportFrom和ST_CreateRast方式导入,具体SQL语句如下:
INSERTINTO raster_table SELECT1,'TIFF', ST_ImportFrom('chunk_table','OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/mybucket/data/G50E009001DOM.tif');INSERTINTO raster_table SELECT2,'TIFF', ST_CreateRast('OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/mybucket/data/G50E009001DOM.tif');
导入成功后,通过查询结果可以看到两种方式都会创建一个raster对象,并且生成的raster对象都可以使用Ganos提供的栅格相关UDF进行操作,如下:
SELECT id,ST_Georeference(rast),st_extent(rast),ST_NumBands(rast),ST_SRID(rast),st_value(rast,0,100,100),st_value(rast,1,200,200)FROM raster_table;
输出结果:
但是ST_ImportFrom方法会创建一个新的表(chunk_table)用于保存具体像素值信息,此时即使原始影像删除也不会影响我们的使用。而ST_CreateRast则仅仅只创建了一个raster对象,其中包含了对外部影像的逻辑映射信息,但具体数据仍然以文件方式存在OSS上。
2. HDF5/NetCDF数据入库
HDF5/NetCDF是另外两种常见的栅格数据格式,广泛适用于地球对地观测、科学计算等领域,尤其在气象、海洋、地球科学相关领域有非常广泛应用。ST_ImportFrom和ST_CreateRast函数同样支持HDF5/NetCDF类型的数据导入,SQL语法也与前面基本相同:
INSERTINTO raster_table Select3,'NC', ST_ImportFrom('chunk_table','OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/Z_NAFP_C_BABJ_20210430000556_P_HRCLDAS_RT_CHN_0P01_HOR-WIV-2021043000.nc');INSERTINTO raster_table Select4,'NC', ST_CreateRast('OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/mybucket/data/Z_NAFP_C_BABJ_20210430000556_P_HRCLDAS_RT_CHN_0P01_HOR-WIV-2021043000.nc');
注意,与Tiff不同的是,对于含有subdataset的HDF5/NetCDF文件,在导入时候还需要在文件路径后面注明subdataset的名称,具体方式如下:
对于NetCDF文件:
INSERTINTO raster_table Select5,'NC', ST_ImportFrom('chunk_table','OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/image.nc:sub_name');
而对于HDF5文件:
INSERTINTO raster_table Select5,'HDF5', ST_ImportFrom('chunk_table','OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/image.hdf5://path/sub_name');
另外对于多维度(大于3)的NC/HDF5文件,还需要指定chunkdim参数。这是因为rast在数据库中的chunk是按照(w, h, b)尺寸进行加载和存储的,这里的w为chunk宽,h为chunk高,b为波段数,当nc文件波段数大于3个时候,需要将除去xy坐标后其他所有波段的乘积作为chunk的波段数进行存储。如下面这个nc文件:
这里的dimension除了lat和lon外,还有两个维度time和isobaric。所以我们在使用ST_ImportFrom入库时,必须指定chunkdim的中的波段数为除去lat和lon之外的其他所有波段的乘积(这里是120),这样才能查询到正确的结果。SQL如下:
insertinto nc_table values(1, ST_ImportFrom('nc_rbt','/Users/xiaofei/Data/raster/nc_demo.nc','{"chunkdim":"(256,256,120)"}'));
3. 数据批量入库
对于OSS上的批量数据,需要配合程序脚本进行入库,下面我们以Pyhon为例,展示如何将OSS上的栅格数据批量导入数据库中:
#连接ossauth=oss2.Auth('AK_ID', 'AK_Secret') bucket=oss2.Bucket(auth, '***endpoint***', '***bucket_name***') #连接数据库,获取游标con=psycopg2.connect(database="***dataq***", user="***dde***", options="-c search_path=aster,public", # 模式password="******", host="*******", port="******") cur=con.cursor() #入库的SQL语句insert_sql="INSERT into {raster_table_name}(filename, band_index, raster_obj) VALUES ..."# 从oss中获取所有hdf5文件名,并保存forobjinoss2.ObjectIterator(bucket, prefix="..."): ff=open("upload.txt", mode='a', encoding='utf-8') filename=obj.key.split('/')[-1] iffilename.find(".hdf5") ==-1: continueelse: ff.write(filename+'\n') # 获取文件列表fileList= {} withopen('upload.txt', 'r') asf: fileList=f.read().split('\n') # 遍历文件列表,生成sql并入库forfileinfileList: # 编辑insert_sql,添加参数...#入库:try: cur.execute(insert_sql) con.commit() logging.info(filename+" finished") except (Exception, psycopg2.Error) ase: logging.info(filename+" error!") print(filename+" 上传失败\n")
总结
综上,云原生数据有其自身独特的数据写入方式,Ganos函数级的导入工具可以帮助用户构建SQL级别的入库-查询-分析-服务一体化能力,用户不需要在不同的业务阶段使用不同的手段操作数据,工作流程标准,易用性高。Ganos在三维数据、轨迹数据的导入方面也同样使用了类似方式,后续会专题开展详细介绍。