将Oracle几何行从大地移植到笛卡儿

时间:2014-12-09 20:07:34

标签: oracle oracle11g spatial

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

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

我创建了表格,

create table granule_cartesian  (
        granule varchar(64) not null,
        SHAPE sdo_geometry NOT NULL );

并插入正确的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);

现在我想将granule的几何内容复制到granule_cartesian。

显然,由于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... 

如果我选择小于~10k(约+/- 10分钟)的颗粒表子集,则此方法有效。任何超过10K和几小时的运行,有时不合理地断开我。

似乎应该有一种方法可以做到这一点而不做< 10K块。除了将FOREVER实际迁移之外,这将对我们的主动和动态生产数据库造成严重的后勤噩梦。我尝试过像这样使用SDO_CS.TRANSFORM:

SDO_CS.TRANSFORM(geom => shape, to_srid => null )

...但是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

SDO_CS.TRANSFORM_LAYER将拒绝接受NULL SRID。

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

编辑

1)对于Clarity,我理解我可以使用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

这是一个强大的企业级服务器,只有oracle。我们最近有一个Oracle顾问(来自Oracle)分析我们所有的数据库系统(包括这个)。它给了一个干净的健康状况。

2 个答案:

答案 0 :(得分:0)

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

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

alter table [table] nologging ; or alter tablespace [tablesspace] nologging ;

这应该会让你失去重做空间,但如果你的重做空间不足,你的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 ;

有400万行,这应该在几分钟内发生,如果不是你的数据库严重失控。

确保您与DBA一起工作

当流程完成后,重建此域索引。这可能需要几个小时。上次我在6400万行上做了它花了3天。您必须了解R-Trees本质上是索引中的索引,并使用最小边界矩形来获得速度,并且它们需要时间来构建,因为每个插入代表来自 root的遍历指数。

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

答案 1 :(得分:0)

BrianB, 抱歉,我只是无法理解您在尝试使用SDO_GEOMETRY(SDO_UTIL.TO_WKTGEOMETRY(shape),null)进行转换。如果我做对了,生成的几何体将具有与源形状相同的几何类型,点,线段和纵坐标。 所以,如果这是真的,你可以使用其中一个:

create table granule_cartesian  (
    granule varchar(64) not null,
    SHAPE sdo_geometry NOT NULL );

insert into granule_cartesian
select  granule, shape
from    granule
where   platform = 'ZZ'; -- granule has a few other columns... 

update granule_cartesian t
set t.shape.sdo_srid = null;

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); -- add metadata after all rows are updated to null srid

或者,如果由于某种原因你讨厌插入然后更新,还有另一种方法:

insert into granule_cartesian
select  granule, mdsys.sdo_geometry (t.shape.SDO_GTYPE, null, t.shape.SDO_POINT, t.shape.SDO_ELEM_INFO, t.shape.SDO_ORDINATES)
from    granule t
where   platform = 'ZZ'; -- granule has a few other columns... 

在这种情况下,在将行插入granule_cartesian之前,您可以在user_sdo_geom_metadata表中添加一行甚至是空间索引。

第h。祝你好运。