将 Oracle 几何行从大地坐标迁移到笛卡尔坐标

Bri*_*anB 5 oracle spatial oracle11g

我有一个表 ( granule),其中包含大约 400 万个当前 SRID = 8307 的唯一几何对象。

我正在尝试创建一个具有相同数据的第二个表,但使用笛卡尔坐标系。

我创建了表,

create table granule_cartesian  (
        granule varchar(64) not null,
        SHAPE sdo_geometry NOT NULL );
Run Code Online (Sandbox Code Playgroud)

并插入正确的geom_metadata

insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values ( 'GRANULE_CARTESIAN', 'SHAPE',
        mdsys.sdo_dim_array(
                mdsys.sdo_dim_element('longitude', -180, 180, .5),
                mdsys.sdo_dim_element('latitude', -90, 90, .5)),
        null);
Run Code Online (Sandbox Code Playgroud)

现在我想将颗粒的几何内容复制到颗粒_笛卡尔中。

显然,由于 SRID 不匹配,直接复制将无法工作。

我可以通过转换为 wkt 并返回到几何体、剥离 SRID 来一次复制几个:

insert into granule_cartesian
select  granule, 
        SDO_GEOMETRY(SDO_UTIL.TO_WKTGEOMETRY(shape), null) as shape
from    granule
where   platform = 'ZZ'; -- granule has a few other columns... 
Run Code Online (Sandbox Code Playgroud)

如果我选择小于 ~ 10k(大约 +/-10 分钟)的颗粒表子集,则此方法有效。如果超过 10K,就会运行几个小时,有时会不礼貌地断开连接。

似乎应该有一种方法可以在不执行 <10K 块的情况下执行此操作。除了需要永远进行实际迁移之外,这还会对我们活跃且动态的生产数据库造成严重的后勤噩梦。我尝试过像这样使用 SDO_CS.TRANSFORM :

SDO_CS.TRANSFORM(geom => shape, to_srid => null )
Run Code Online (Sandbox Code Playgroud)

...但是 oracle 不会在这里接受 NULL SRID:

 12:57:49  [SELECT - 0 row(s), 0.000 secs]  [Error Code: 1405, SQL State: 22002]  ORA-01405: fetched column value is NULL
ORA-06512: at "MDSYS.SDO_CS", line 114
ORA-06512: at "MDSYS.SDO_CS", line 152
ORA-06512: at "MDSYS.SDO_CS", line 5588
ORA-06512: at "MDSYS.SDO_CS", line 3064
Run Code Online (Sandbox Code Playgroud)

SDO_CS.TRANSFORM_LAYER 将拒绝接受 NULL SRID。

经过广泛的搜索,我找不到任何方法来进行简化的大地测量 - >笛卡尔(SRID = NULL)转换。除了暴力小批量之外,还有人有任何想法吗?

编辑

1) 为了清晰起见,我知道我可以使用 PL/SQL 将其分解并执行 450 个 10K 行块。但是每块大约 470 秒,仍然是 2.5 天的执行时间。这是最好的情况。使用更改投影/坐标系update granule set shape.srid = 8307既快速又简单。使用将坐标系从笛卡尔坐标系更改为大地坐标系insert into granule select SDO_CS.TRANSFORM(geom => shape, to_srid => 8307 ) ....既快速又简单。我正在寻找一种同样简单/快速的解决方案,从大地测量到笛卡尔。

2)尝试插入300K作为测试。运行了大约10个小时就这样死掉了:

 20:06:59  [INSERT - 0 row(s), 0.000 secs]  [Error Code: 4030, SQL State: 61000]  ORA-04030: out of process memory when trying to allocate 8080 bytes (joxcx callheap,f:CDUnscanned)
ORA-04030: out of process memory when trying to allocate 8080 bytes (joxcx callheap,f:CDUnscanned)
ORA-04030: out of process memory when trying to allocate 16328 bytes (koh-kghu sessi,kgmtlbdl)
ORA-06512: at "MDSYS.SDO_UTIL", line 2484
ORA-06512: at "MDSYS.SDO_UTIL", line 2511
Run Code Online (Sandbox Code Playgroud)

这是一个强大的企业级服务器,除了 Oracle 之外什么都没有。最近,我们请了一位 Oracle 顾问(来自 Oracle)分析我们所有的数据库系统(包括这个)。它获得了健康证明。

Fly*_*Guy 0

数据库出现问题。我有包含 6400 万行的 geom 表(北美的每一条地图道路 - 是的,加拿大、美国和墨西哥),我经常执行 sdo_anyinteract / sdo_contains 查询,并在不到 5 秒的时间内获得 200 平方英里的响应。

首先,删除所有索引并关闭目标表或表空间上的日志记录。如果您没有权限,请询问您的 DBA,但命令是:

alter table [table] nologging ; or alter tablespace [tablesspace] nologging ;
Run Code Online (Sandbox Code Playgroud)

这应该可以防止重做空间耗尽,但如果重做空间耗尽,DBA 应该通过添加重做段来解决这个问题。

使用游标是因为在接收 WKT 时必须添加 SRID,因为必须在 SDO 对象上设置 SRID。

declare

newGeom sdo_geometry ;

begin

 for rec in ( select statement ) loop

    newGeom := sdo_util.to_wktgeometry(rec.geom);
    newGeom.sdo_srid := [srid that matches the target ] ;

   insert into [table] (geom column, ... )values( newGeom, ... );

 end loop;

 commit ;

end ;
Run Code Online (Sandbox Code Playgroud)

对于 400 万行,这应该会在几分钟内发生,否则您的数据库就会严重失常。

确保您与 DBA 一起工作

该过程完成后重建该域索引。这可能需要几个小时。上次我对 6400 万行执行此操作花了 3 天。您必须了解 R 树本质上是索引中的索引,并使用最小边界矩形来提高速度,并且它们需要很长时间才能构建,因为每次插入都代表从索引根开始的遍历。

您可以使用BULK COLLECT之类的东西,但这对于这个地方来说太复杂了。我建议,如果您还没有一个 Oracle 帐户(它们是免费的),并在 Oracle 论坛的数据库 -> 空间下提出这样的问题