拓冰建站拓冰建站
首页 / 资讯中心 / 正文

KingbaseES空间数据迁移全流程:PostGIS到人大金仓的GIS数据搬迁与SRID校验

简介人大金仓 KingbaseES V8.6 GIS 数据迁移方案面向需要将 ArcGIS、GeoScene、SuperMap 等平台中的矢量、栅格空间数据迁入国产数据库 KingbaseES 的数据库管理员和 GIS 应用开发者。文档先介绍 KingbaseES 的 GIS 能力及与常见 GIS 软件的关系随后按平台分别给出迁移路径基于 KDTS 工具的 ETL 式迁移利用 ArcGIS/GeoScene 软件直接导入通过 SuperMap 工具或 API 迁移并补充第三方通用 GIS 文件入库方法。各章节均包含详细操作步骤、迁移结果验证和 FAQ可帮助规避坐标系不一致、属性丢失等常见问题。资源为 1 个 PDF 文件压缩包大小 2.76MB目前已有 133 人学习浏览。整体内容贴近实际实施场景文档共五章、按平台划分适合在国产化替代、GIS 平台切换或数据整合项目中作为直接参考。1. 为什么需要一份 KingbaseES 的 GIS 数据迁移方案空间数据迁移比想象中更吃细节信创替换推进到地理信息这一层时最让人头疼的往往不是业务表而是带 geometry 字段的图层表。人大金仓 KingbaseES v8.6 在 PostgreSQL 兼容模式下通过 postgis 扩展承载空间能力理论上迁移路径顺畅但「兼容」不等于按下按钮就能跑坐标系 SRID、空间索引、ST_ 函数差异会在迁移过程中接二连三冒出来一个没对齐图层整体漂移几十公里。下面按我实际做过的路径写先盘点、再迁移、最后统一校验。目标读者是正在做国产化替换的 DBA、GIS 实施工程师以及用 ArcGIS / QGIS 对接 KingbaseES 的同事。读完可以不改命令直接跑也可以拿排查思路去定位手头项目的问题。2. 迁移前的准备空间扩展、授权与源库盘点GIS 数据迁移和其他数据迁移最大的区别在于空间数据除了「值」还有「坐标系」和「空间参考」这套元数据。元数据不对数据本身再完整也白搭。所以在连接数据库之前先把目标库的空间承载能力确认好再把源库的空间对象摸一遍底。2.1 KingbaseES v8.6 的空间能力从哪里来扩展、授权和 geometry 类型选择KingbaseES v8.6 对 GIS 数据的承载方式有两条路线。第一条走 PostgreSQL 兼容模式创建 postgis 扩展用 geometry 和 geography 类型存空间数据第二条走 Oracle 兼容模式用 SDO_GEOMETRY 类型。对绝大多数从 PostgreSQL/PostGIS 迁来的场景用第一条对原本在 Oracle Spatial 里维护、且应用代码大量依赖 SDO 函数的场景才需要考虑第二条。判断起来很简单看源库的字段类型和 SQL 写法。这两条路线在实施前都有各自的准备项。PostGIS 路线要确认安装目录里的空间组件存在、授权文件覆盖 GIS 特性SDO 路线要确认兼容模式的数据库实例已经正确初始化。我见过不止一次迁移工具配置好、表和字段都识别到了结果 CREATE EXTENSION 阶段直接报错最后发现是安装时没有勾选 GIS 组件或者授权文件是基础版、不含空间模块。这类问题在项目启动阶段暴露代价最小所以开库第一件事就跑一遍下面的确认。-- 在 KingbaseES 中启用空间扩展幂等可重复执行 CREATE EXTENSION IF NOT EXISTS postgis; -- 查看扩展版本与源库 PostGIS 版本做比对 SELECT extversion FROM pg_extension WHERE extname postgis; -- 确认空间参考表存在且有数据 SELECT count(*) FROM spatial_ref_sys;第一句是幂等操作重复执行不会报错可以放心放进初始化脚本第二句返回当前实例的 postgis 扩展版本迁移前把源库和目标库的版本号写在一起能提前判断哪些 ST_ 函数可能因版本差异不兼容第三句如果返回 0 行或直接报错说明扩展没装完整后边的 SRID 转换和坐标系标准化无从谈起。如果只是快速验证功能目标物理机还没到位用官方 docker 镜像起一个单机实例也能跑通大部分迁移流程但坐标转换和性能验证最终还是要回到真实环境做。这三条 SQL 我每次新建目标库都要跑一遍算是迁移前必做的体检。扩展确认可用之后还有一个容易纠结的点geometry 和 geography 到底选哪个。我的建议是迁移时保留源库的类型源库是 geometry 就迁成 geometry不要顺手「升级」成 geography。原因有两条一是 geometry 走平面计算性能和函数支持度都比 geography 好国内坐标系多数是 CGCS2000 / 高斯克吕格这类投影坐标用 geometry 贴合业务习惯二是地理信息平台ArcGIS / QGIS对接 geometry 的操作路径更成熟。只有源库明确用了 geography 做球面距离计算才需要原样保留。2.2 盘点源库空间字段、SRID 与记录量一次查清迁移方案落地前我习惯先把源库的空间对象摸一遍底。摸底的目的是回答三个问题哪些表带有空间字段、字段用的坐标系是什么、总共多少行数据。这三个答案直接决定迁移走哪条路径、要不要做坐标转换、装载批次怎么定。最怕的情况是迁移工具已经跑了一半才发现有几张图层表没被识别成空间表被当成普通文本字段搬了过去。源库是 PostgreSQL 系列时用下面的 SQL 直接查出所有空间表SELECT n.nspname AS schema_name, c.relname AS table_name, a.attname AS column_name, t.typname AS data_type FROM pg_attribute a JOIN pg_class c ON a.attrelid c.oid JOIN pg_namespace n ON c.relnamespace n.oid JOIN pg_type t ON a.atttypid t.oid WHERE t.typname IN (geometry, geography) AND a.attnum 0 AND NOT a.attisdropped ORDER BY n.nspname, c.relname, a.attnum;这里查系统目录而不是 information_schema是因为空间类型在 information_schema 里经常不会被识别为标准 data_type直接查 pg_type 反而最稳。源库是 Oracle 时改用 all_tab_columns-- 源库是 Oracle 时查 SDO_GEOMETRY / ST_GEOMETRY 字段 SELECT owner, table_name, column_name, data_type FROM all_tab_columns WHERE data_type IN (SDO_GEOMETRY, ST_GEOMETRY) ORDER BY owner, table_name;如果源库用的是 ArcGIS SDE 管理的要素类还要额外留意 SDE 注册表里的元数据。SDE 会把要素注册信息放在 sde_layers 和 sde_table_registry 里直接迁字段本身不复杂但迁完之后 ArcGIS 可能不认这个表是要素类。常见做法是在迁移方案里为 SDE 源单独留一个「重建要素类注册」步骤而不是只搬数据。摸清空间表之后再对每张表做一次快速体检-- 对每个空间表统计记录数、SRID 集合、空间范围 SELECT count(*) AS feature_count, array_agg(DISTINCT ST_SRID(geom)) AS srid_list, ST_Extent(geom) AS bbox FROM public.parcels;这段 SQL 能一眼看出三个关键信息feature_count 是零说明源表本身没有有效要素srid_list 如果出现多个值说明表内坐标系不统一迁移前要先定一个统一的目标 SRIDbbox 范围是最低成本的空间一致性校验基线迁移后用同一句 SQL 返回范围两个范围对不上就说明有数据丢失或坐标变换出错。对每张空间表跑一遍这三个指标总耗时通常很短却能把后面一多半的坑提前排掉。2.3 迁移路径怎么选直连工具、文本脚本还是分批装载盘点结果出来之后根据数据量和结构选迁移路径。我一般分三种迁移路径适用场景优点主要风险图形化迁移工具直迁数据量小、SRID 统一、字段类型简单操作直观表结构自动生成空间索引要手工建SRID 可能被工具忽略SQL 文本导出 装载数据量大、字段有特殊处理需求每一步可控能定位脏数据便于脚本化要写转换 SQL整体耗时较长分批 断点续传几十 GB 以上或跨网络传输失败只重传当前批次对生产影响小需要调度逻辑工作量大判断依据很直接几十万行的空间表图形化直迁最快上亿行的地类图斑必须走分批装载源库还在持续更新时则在存量迁移之外预留增量同步的接口。下面第 3 章把这三条路径展开重点给出第二条文本装载的完整脚本——这是我在项目里最常用、也最不容易翻车的一条路。另外补一条选型经验如果源库字段里混着自定义类型、数组或者 JSONB直连迁移工具经常在这些字段上卡住。我的做法是先选两张代表性小表试迁一张是纯空间字段加基础类型的另一张是带复合字段的。小表跑通再放量小表跑不通直接转文本路径。这个试迁步骤看着浪费时间实际能省下后面一整天的排错。3. 把空间数据迁进 KingbaseES图形化直迁与文本装载脚本这一章是实操重点。按第 2.3 节的选型结论规模小的走直迁规模大的走文本脚本两种情况我都会把关键命令和收尾步骤写出来。3.1 直连工具迁移适合结构简单的图层表KingbaseES 的图形化对象迁移工具KDB Migration Toolkit 一类是直迁的主力。常见做法是在工具里分别配置源库和目标库连接勾选需要迁移的空间表工具会自动生成目标库的建表语句并搬运数据。对 PostgreSQL 源的 geometry 字段工具通常能识别为空间类型直接映射到目标库的 geometry对 Oracle 的 SDO_GEOMETRY部分版本需要先在目标库手工建好带 SDO 语义的表再让工具只搬运数据。但直迁有两个坑是工具帮不了你的。第一空间索引不会自动创建。原表上的 GIST 索引在目标库就是一张空索引迁移完必须手工重建。第二SRID 的传递经常静默失败。工具把 geometry 列搬过去了列的类型修饰符里却没有 SRID 信息看起来数据都在实际上坐标系统已经丢了。所以我每次用工具迁移完都会先跑一遍-- 检查目标库空间字段的类型修饰符正常应包含 SRID SELECT f_table_name, f_geometry_column, srid, type FROM geometry_columns WHERE f_table_name parcels;geometry_columns 视图是 postgis 扩展维护的元数据视图srid 一列直接反应列定义时的坐标系。如果查到 srid 是 0说明工具没把 SRID 带过来需要按源库坐标系手工做 ST_SetSRID。这一步是直迁路线最容易忽略的检查点。另外直迁工具的批量提交大小要注意。默认的批量值在大表上会生成极长事务一旦中途出错回滚代价很高。我一般把批量提交改成 1000 行左右慢是慢一点但每批独立提交失败定位到具体批次配合日志看进度比一次性提交稳得多。3.2 文本装载路径导出、建表、转换三步骤直迁搞不定的场景我一般切到文本装载。思路很简单把空间数据导出成带 SRID 的文本EWKT到目标库先存文本再统一转成 geometry 类型。这样每一步都可控脏数据能精确到行而且整个过程可以用 shell 脚本串起来反复执行。第一步在源库把空间表导出为 CSV# 在源库把空间数据导出为带 SRID 的文本 psql -h 192.168.1.10 -U gis_user -d gis_db SQL \COPY ( SELECT id, name, ST_AsEWKT(geom) AS geom_wkt FROM public.parcels ) TO /tmp/parcels.csv WITH (FORMAT csv, HEADER true); SQL用 ST_AsEWKT 而不是 ST_AsText是因为 EWKT 格式会把 SRID 写进文本里形如 SRID4326;POLYGON(...)。这相当于把坐标系的元数据一起带走避免出现「数据到了、坐标系丢了」的尴尬。如果源表还有属性字段直接在 SELECT 里追加列即可但列顺序务必和后续建表语句里的列顺序保持一致\copy 是按列位置装载的列序错位是最常见的低级翻车。第二步在目标库建表。这里的关键是 geometry 列必须显式带上 SRID-- 目标库建表SRID 按源库盘点结果填 CREATE TABLE public.parcels ( id bigint, name varchar(100), geom geometry(Geometry, 4326), geom_wkt text );建表时把 geom 的类型修饰符写死为 geometry(Geometry, 4326)意思是「通用几何类型固定用 4326 坐标系」。这个修饰符会注册到 geometry_columns 视图里GIS 平台读取时直接认坐标系。临时列 geom_wkt 用来承接 CSV 里的文本装载完数据后删除。第三步装载文本并转为空间类型-- 用 ksql 装载 CSV 文本 \copy public.parcels(id, name, geom_wkt) FROM /tmp/parcels.csv WITH (FORMAT csv, HEADER true); -- 文本转 geometry源里有 SRID 直接带过来 UPDATE public.parcels SET geom ST_GeomFromEWKT(geom_wkt) WHERE geom_wkt IS NOT NULL; -- 清理临时列 ALTER TABLE public.parcels DROP COLUMN geom_wkt;\copy 是客户端侧装载命令CSV 文件在运行命令的机器上读取适合数据文件已经落地的场景如果数据文件已经在目标库服务器磁盘上可以换成 COPY 命令省去客户端传输。UPDATE 里的 ST_GeomFromEWKT 会解析文本中自带的 SRID解析失败时只报当前行的错误配合 WHERE 条件可以快速定位脏数据行这是文本路径最大的优势。这里有一个小参数值得注意UPDATE 一次性更新千万行时建议先去掉表上的非必要约束并把 work_mem 临时调大否则更新阶段的排序和索引维护会成为瓶颈。提示EWKT 文本里的 SRID 前缀是迁移过程的「后悔药」导出时务必保留导入后还要回 geometry_columns 里确认一次别等 GIS 平台叠加底图时才发现坐标系没带。3.3 大表分批装载分片、循环和断点续传单表数据量超过千万行或者几十 GB 时一次 \copy 装进去容易把事务撑爆中途失败还得全量重来。我一般按主键分片每片控制在百万行以内循环装载# 按主键分片循环装载每片 100 万行 for ((offset0; offsetTOTAL_ROWS; offset1000000)); do psql -h source_host -U gis_user -d gis_db -c COPY ( SELECT id, name, ST_AsEWKT(geom) FROM public.parcels WHERE id ${offset} ORDER BY id LIMIT 1000000 ) TO STDOUT WITH (FORMAT csv, HEADER false); /tmp/parcels_chunk.csv # 每片装载完成后立即记录断点便于续传 echo loaded offset${offset} at $(date) /tmp/migration.log done这个循环的断点记录在日志里失败时查日志看最后一个成功的 offset从这个位置继续而不是整表重来。实际项目中如果源库和目标库网络带宽有限更常见的方式是每个分片导出成独立文件再用 \copy 逐个装载避免一次大事务拖垮两端。需要说明的是分批装载的几何数据在全部装完之前目标表的约束和索引都不要提前建等数据完整后再统一建这样能省下大量索引维护时间。分片键的选择也有讲究。主键是数字序列最好没有数字主键的表可以用空间范围分片例如按 1 度网格把数据切成若干小块导出。空间分片的好处是每个分片内的几何对象空间上相邻目标库写入时的页面缓存命中率更高装载速度反而比随机主键分片快。3.4 迁移收尾重建 GIST 空间索引与统计信息数据装完最后一步是建空间索引和更新统计信息。这一步不做查询全表扫描GIS 平台出图直接卡死。-- 装载完成后创建 GIST 空间索引 CREATE INDEX idx_parcels_geom ON public.parcels USING gist (geom); -- 更新统计信息让优化器拿到空间数据分布 ANALYZE public.parcels; -- 验证空间范围与源库盘点结果一致 SELECT ST_Extent(geom) FROM public.parcels;GIST 是 PostGIS 空间索引的标准访问方法普通 B-Tree 对 geometry 类型不适用。建索引前可以根据数据量调大 maintenance_work_mem比如 4GB 内存的实例设成 1GB索引创建能快不少但要注意这个参数是会话级还是实例级别在共享实例上直接改全局配置。ANALYZE 这一步很多迁移方案会漏掉漏掉的直接后果是空间查询不走索引后期被业务方当成「数据库性能不行」来投诉。最后那句 ST_Extent 就是把第 2.2 节盘点的 bbox 基线拿出来对比范围对不上说明数据在装载中有丢失必须返工。4. KingbaseES GIS 迁移的 5 个典型坑与排查方法这里整理的 5 个问题来自我实际参与过的迁移项目按出现的频率排序。每一条都是「现象 → 原因 → 解决」的结构可以直接对照自己的报错排查。需要提醒的是这 5 个坑在同一个项目里往往不是单一出现排查顺序建议固定为「扩展 → SRID → 精度 → 编码 → 索引」顺序反了会陷入「索引报错其实是 SRID 引起」这种交叉问题里。4.1 扩展装不上CREATE EXTENSION postgis 一直报错现象执行 CREATE EXTENSION postgis 时返回类似 ERROR: extension postgis is not available 或者 permission denied数据库里查不到 postgis 扩展。原因最常见的是安装时没选装 GIS 组件postgis 的扩展文件根本没放进数据库的 extensions 目录其次是授权文件不含 GIS 特性权限校验在扩展创建阶段就拦住了。这两种情况报错信息差不多光看日志很难区分。解决先确认安装目录里有没有 postgis 相关文件没有就重装或补装 GIS 组件有文件则检查授权文件是否覆盖空间模块必要时重新加载授权。之后重跑 CREATE EXTENSION。这个坑最好在项目启动阶段排除不要等迁移工具跑一半再来查。4.2 图层漂到海里SRID 在迁移中静默丢失现象数据迁完在 QGIS 或 ArcGIS 里打开图层要素全堆在坐标原点附近叠加天地图底图时完全对不上位置整体偏移几十公里甚至跑到海里。原因geometry 列的 SRID 在迁移中变成 0。源库的字段类型修饰符带了 SRID但迁移工具或文本脚本只搬了「值」没搬「坐标系」。GIS 平台读取图层时按 SRID 0 处理自然以为是经纬度或本地坐标。解决检查 geometry_columns 视图确认目标表 srid 是否为 0是 0 就按源库坐标系统一纠正-- 统一设置坐标系按源库实际 SRID 填写 UPDATE public.parcels SET geom ST_SetSRID(geom, 4326) WHERE ST_SRID(geom) 0;ST_SetSRID 只改元数据不改变坐标数值所以前提是迁移过程中数值没有被错误的坐标系解释过。如果数据已经被当成别的坐标系处理过一轮那就只能用 ST_Transform 换回来这时需要源库和目标库的原始 SRID 都明确才行。迁移前把源库 SRID 记录在案是避免这个坑最有效的办法。4.3 面积越算越不对精度位数被悄悄截断现象迁移后用 ST_Area 计算图斑面积和源库结果差出百分之几做面积平差时对不上账。原因常见两处。一是建表时把数值精度写小了比如把源库的 numeric(38,8) 建成了 numeric(10,2)面积的小数位直接丢失二是 CSV 文本导出时用了默认精度把 double precision 坐标缩短成 6 位小数一个 400 公里范围的县界坐标 6 位小数和 15 位小数算出来的面积能差出一条街来。解决建表语句里显式声明精度坐标字段用 double precision属性字段数值型按源库最大精度展开文本导出时用 ST_AsEWKT 输出完整精度不要在导出阶段用 round 截断坐标。迁移后用抽样图斑对比 ST_Area是验证这一步是否出错最直接的手段。如果源库数据本身存在拓扑瑕疵比如图斑有自相交迁移后面积差异会和精度问题混在一起需要先在源库做一轮 ST_IsValid 检查。4.4 名字全变乱码客户端编码没对齐现象迁完数据中文地名、权利人名称全是乱码源库里明明是正常中文。原因源库字符集是 GBK目标库是 UTF8导出和装载过程中客户端编码没有显式指定字符在转换时被错误解释了一遍。解决导出前和导入前都设置客户端编码保持文件两端一致# 导出侧告诉 psql 按源库编码输出 export PGCLIENTENCODINGGBK # 导入侧告诉 ksql 按目标库编码读取 export PGCLIENTENCODINGUTF8如果 CSV 文件已经导出完才发现乱码可以用 iconv 把文件从 GBK 转成 UTF8 再装载。注意 \copy 装载时和文件编码要保持一致不要让数据库再猜一次。4.5 空间索引建不出来类型修饰符与扩展版本冲突现象执行 CREATE INDEX ... USING gist (geom) 报错提示 data type geometry has no default operator class。原因有两种典型情况。一是 postgis 扩展没创建成功geometry 类型不是真正的空间类型二是这个 geometry 列来自直迁工具列定义里带着来源库的旧类型修饰符与目标库的 postgis 版本不匹配。解决先确认扩展可用再检查列的类型-- 确认扩展和列的类型归属 SELECT extversion FROM pg_extension WHERE extname postgis; SELECT geom::regtype FROM public.parcels LIMIT 1;如果列的 regtype 显示为不带 postgis 语义的普通类型最干净的做法是删掉该列重新按 geometry(Geometry, SRID) 添加再用第 3.2 节的文本流程重灌这一列。强行在坏列上创建索引会消耗大量时间还未必成功。5. 迁移后的校验三板斧范围比对、索引验证与增量同步5.1 用 ST_Extent 和 ST_Area 做空间一致性校验迁移完成后不要急着交接。我先跑三句校验 SQL把结果和源库盘点基线对齐count(*) 看行数、ST_Extent 看空间范围、抽 50 条要素用 ST_Area 对比面积。范围对不上说明有数据缺失或坐标转换错误这是红线问题面积对不上多半是精度问题按 4.3 处理。三句校验都通过才说明这批数据真正可用。-- 迁移后校验数量、范围、抽样面积 SELECT count(*), ST_Extent(geom) FROM public.parcels; SELECT id, ST_Area(geom) FROM public.parcels ORDER BY id LIMIT 50;面积对比时注意源库和目标库用同一个 SRID 计算如果源库是投影坐标、目标库是经纬度直接比对 ST_Area 没有意义要先统一坐标系再做数值对比。校验脚本建议保存成.sql文件纳入迁移交付文档后续再有数据更新可以重复跑同一套脚本做回归。5.2 用 EXPLAIN 验证空间索引真正生效索引建了不等于查询会走索引优化器一旦对空间数据分布误判可能宁可全表扫描。验证方法用空间查询的典型写法看执行计划EXPLAIN (ANALYZE, BUFFERS) SELECT count(*) FROM public.parcels WHERE geom ST_MakeEnvelope(120.1, 30.2, 120.9, 30.8, 4326);是空间 bounding box 相交操作符是索引快速过滤的核心。执行计划里出现 Bitmap Index Scan on idx_parcels_geom 说明索引生效出现 Seq Scan 则要回头检查是否漏建索引、统计信息是否更新。然后把矩形范围换成业务真实的行政范围再试一次避免拿一个很小的测试框验证得出「走得挺好」的假结论。如果源库还在生产并持续更新增量同步的可行做法是按业务更新时间字段每天拉新增记录在目标库先删除同 ID 的旧记录再插入新记录保持两侧一致没有时间字段的表则要评估是否允许短时锁表做全量替换。我最早做 GIS 迁移时就是没在迁移前记录 SRID 基线图层叠加天地图偏了十几公里反复怀疑数据和工具最后才查到是 SRID 静默丢失。从那以后每次动手前先做盘点、落一份基线表格存档迁移后逐项核对。这套流程看着笨但确实让后面的项目再没有因为坐标系问题返工过。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门