Oracle Spatial 函数 SDO_CS.Transform(value) 结果真的很慢
Oracle Spatial function SDO_CS.Transform(value) results really slow
我有一个自定义视图,它从几何列中查询空间数据并提取 latitude/longtitude 值。但是,检索过程真的很慢,检索视图数据最多需要 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 table 有 1,310,629 行,而 PoleDetailPoint 有 100 行。此 table 中的数据每天更新,而视图用于报告目的。
我尝试使用 status=cleanup
参数重建空间索引。但这没有任何区别。
我们的版本是Oracle 11.2.0.3。
对于检索此类 views/data 的任何提示,我们表示赞赏。或者我可以使用任何其他空间函数来更快地实现这一目标?
您是否尝试将强制转换为 table 个元素移动到 with 子句?
通常它们非常慢,特别是如果优化器决定为连接中的每一行 运行 它们 table(检查结果集是否已更改)
试试这个:
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
)
问候
奥拉维尔
尝试使用 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 * 5 条记录,其中一条记录对应 5 的 T 和 T2 的 25 种可能组合中的每一种顶点 P.G3E_GEOMETRY
。我不知道顶点顺序是否由 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;
我有一个自定义视图,它从几何列中查询空间数据并提取 latitude/longtitude 值。但是,检索过程真的很慢,检索视图数据最多需要 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 table 有 1,310,629 行,而 PoleDetailPoint 有 100 行。此 table 中的数据每天更新,而视图用于报告目的。
我尝试使用 status=cleanup
参数重建空间索引。但这没有任何区别。
我们的版本是Oracle 11.2.0.3。
对于检索此类 views/data 的任何提示,我们表示赞赏。或者我可以使用任何其他空间函数来更快地实现这一目标?
您是否尝试将强制转换为 table 个元素移动到 with 子句?
通常它们非常慢,特别是如果优化器决定为连接中的每一行 运行 它们 table(检查结果集是否已更改)
试试这个:
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
)
问候 奥拉维尔
尝试使用 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 * 5 条记录,其中一条记录对应 5 的 T 和 T2 的 25 种可能组合中的每一种顶点 P.G3E_GEOMETRY
。我不知道顶点顺序是否由 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;