【问题标题】:Oracle Spatial function SDO_CS.Transform(value) results really slowOracle Spatial 函数 SDO_CS.Transform(value) 结果真的很慢
【发布时间】:2015-09-03 22:04:04
【问题描述】:

我有一个自定义视图,它从几何列查询空间数据并提取纬度/经度值。但是,检索过程确实很慢,需要 5 到 10 分钟才能检索到视图数据。

这是我的看法:

CREATE OR REPLACE FORCE VIEW PoleData
(
   G3E_FID,
   X_COORD,
   Y_COORD,
   LATITUDE,
   LONGITUDE
)
AS
   SELECT P.g3e_fid,
          T2.X * 1000 AS x_coord,
          T2.Y * 1000 AS y_coord,
          T.Y AS latitude,
          T.X AS longitude
     FROM PolePoint P,
          TABLE (
             SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
          TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
    WHERE P.ltt_id = 0
   UNION
   SELECT P.g3e_fid,
          T2.X * 1000 AS x_coord,
          T2.Y * 1000 AS y_coord,
          T.Y AS latitude,
          T.X AS longitude
     FROM PoleDetailPoint P,
          TABLE (
             SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
          TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
    WHERE P.ltt_id = 0;

G3E_GEOMETRY 列属于SDO_GEOMETRY 类型。 PolePoint 表有 1,310,629 行,而 PoleDetailPoint 有 100 行。此表中的数据每天更新,而视图用于报告目的。

我尝试使用status=cleanup 参数重建空间索引。但这并没有什么不同。

我们的版本是 Oracle 11.2.0.3。

有关检索此类视图/数据的任何提示表示赞赏。或者我可以使用任何其他空间函数来更快地实现这一点?

【问题讨论】:

  • 为什么这个问题被否决了?投反对票的用户可以评论原因吗?
  • 如果 PolePoint 和 PoleDetailPoint 没有重叠,您可以使用 UNION ALL 而不是 UNION,那么 DB 就不必区分结果了。
  • 你真的需要Union吗?为什么不使用union all?
  • 手头没有时间和数据来摆弄它,但我会尝试提示第一个语句在主表和支持用于空间的嵌套表的隐藏表之间使用散列柱子。我怀疑 NL 使用嵌套表上的索引。能否请您发布执行计划?
  • 您究竟是如何查询此视图的?就像弗洛林建议的那样,一个解释计划会很有用。生成一个这样的:explain plan for select * from PoleData;,然后是select * from table(dbms_xplan.display);。性能可能与 SDO 无关,可能只是一个糟糕的执行计划。

标签: oracle geometry spatial-query spatial-index


【解决方案1】:

尝试使用UNION ALL 而不是UNION:

SELECT P.g3e_fid,
       T2.X * 1000 AS x_coord,
       T2.Y * 1000 AS y_coord,
       T.Y AS latitude,
       T.X AS longitude
  FROM PolePoint P,
       TABLE (
          SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
       TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
 WHERE P.ltt_id = 0
UNION ALL
SELECT P.g3e_fid,
       T2.X * 1000 AS x_coord,
       T2.Y * 1000 AS y_coord,
       T.Y AS latitude,
       T.X AS longitude
  FROM PoleDetailPoint P,
       TABLE (
          SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
       TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
 WHERE P.ltt_id = 0;

另一个导致性能下降的潜在原因是,您使用了两个对SDO_UTIL.GET_VERTICES 的调用,一个直接在P.G3E_GEOMETRY 上,另一个在P.G3E_GEOMETRY 的变换上,您实际上将得到两个顶点的叉积列表,例如,如果一个特定的P.G3E_GEOMETRY 包含 5 个顶点,那么对于该 5 个顶点P.G3E_GEOMETRY,T 和 T2 的 25 种可能组合中的每一种都会得到 5 * 5 条记录。我不知道顶点顺序是否由 SDO_CS.TRANSFORM 函数维护,但如果是,您可以通过在查询的每一半中添加 and t1.id = t2.id 谓词来提高性能:

SELECT P.g3e_fid,
       T2.X * 1000 AS x_coord,
       T2.Y * 1000 AS y_coord,
       T.Y AS latitude,
       T.X AS longitude
  FROM PolePoint P,
       TABLE (
          SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
       TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
 WHERE P.ltt_id = 0
   AND T.ID = T2.ID
UNION ALL
SELECT P.g3e_fid,
       T2.X * 1000 AS x_coord,
       T2.Y * 1000 AS y_coord,
       T.Y AS latitude,
       T.X AS longitude
  FROM PoleDetailPoint P,
       TABLE (
          SDO_UTIL.GETVERTICES (SDO_CS.TRANSFORM (P.G3E_GEOMETRY, 8265))) T,
       TABLE (SDO_UTIL.GETVERTICES (P.G3E_GEOMETRY)) T2
 WHERE P.ltt_id = 0
   AND T.ID = T2.ID;

【讨论】:

    【解决方案2】:

    您是否尝试过将强制转换为表格元素移动到 with 子句?

    通常它们非常慢,特别是如果优化器决定为连接表中的每一行运行它们(以检查结果集是否已更改)

    试试这个:

    with t as (select * from table (sdo_util.getvertices (sdo_cs.transform (p.g3e_geometry, 8265)))),
         t2 as (select * from table (sdo_util.getvertices (p.g3e_geometry)))
    select p.g3e_fid,
           t2.x * 1000 as x_coord,
           t2.y * 1000 as y_coord,
           t.y as latitude,
           t.x as longitude
      from polepoint p, t, t2
     where p.ltt_id = 0
    union 
    select p.g3e_fid,
           t2.x * 1000 as x_coord,
           t2.y * 1000 as y_coord,
           t.y as latitude,
           t.x as longitude
      from poledetailpoint p, t, t2
     where p.ltt_id = 0;
    

    另外,您确定需要"union"(强制排序过滤器)而不是"union all"? (即您是否期望重复结果?如果不使用union all)

    问候 奥拉弗

    【讨论】:

    • 您不能使用 with 子句将强制转换为表元素,因为它们依赖于极点表。注意 p.g3e_geometry 引用。
    • 啊,当然可以。我现在看到了。但这解释了为什么它这么慢。 table(sdo_util.getvertices(...)) 在polepoint 中的每一行运行2 次,在poledetailpoint 中的每一行运行2 次。
    猜你喜欢
    • 1970-01-01
    • 2017-12-07
    • 2013-01-16
    • 2022-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多