问题:
我有一个空间表(路线),使用ESRI的SDE.ST_GEOMETRY
用户定义数据类型存储在Oracle 12c 地理数据库中。我想列出线顶点,以便最终访问并更新它们的坐标。如果使用的是SDO_GEOMETRY / Oracle Locator,则可以使用该
SDO_UTIL.GETVERTICES
功能。但是我没有使用SDO_GEOMETRY / Oracle Locator,并且中没有等效功能SDE.ST_GEOMETRY
。我可以找到的与顶点有关的唯一SDE.ST_GEOMETRY
函数是ST_PointN
和ST_NumPoints
。
我想出一个可以成功完成所有操作的查询-将行顶点作为行(受此页面的启发):
1 SELECT a.ROAD_ID
2 ,b.NUMBERS VERTEX_INDEX
3 ,a.SDE.ST_X(SDE.ST_PointN(a.SHAPE, b.NUMBERS)) AS X
4 ,a.SDE.ST_Y(SDE.ST_PointN(a.SHAPE, b.NUMBERS)) AS Y
5 FROM ENG.ROADS a
6 CROSS JOIN ENG.NUMBERS b
7 WHERE b.NUMBERS <= SDE.ST_NumPoints(a.SHAPE)
8 --removed to do explain plan: ORDER BY ROAD_ID, b.NUMBERS
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 1 | MERGE JOIN | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 2 | INDEX FULL SCAN | R23715_SDE_ROWID_UK | 30 | 90 | | 1 (0)| 00:00:01 |
|* 3 | SORT JOIN | | 3997 | 1018K| 2392K| 261 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL| ROAD | 3997 | 1018K| | 34 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
" 3 - access(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
" filter(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
它将表中CROSS JOINS
的行限制ROADS
为一个NUMBERS
表(并将结果限制为每行中的顶点数)。
统计:(已更新)
- 每行最多有30个顶点(每行平均4.38个顶点)
- ROADS有3,997条线
- NUMBERS有30行(序号从1开始)
- 结果集有17,536行
但是,性能很差(40秒),我不禁想到-有没有更优雅的方法呢?对我来说,使用数字表和交叉联接似乎是一种草率的方法。有没有更好的办法?
外行的条款将不胜感激;我是公共工程人员,不是DBA。
更新#1:
如果我从查询中删除第3行和第4行(与X和Y相关的函数的字符串),它将立即执行。但是,当然,我不能只删除这些行,我需要 X&Y列。因此,这使我相信,性能下降与X&Y函数有关。
但是,如果将点导出到静态表中,然后在其上运行X&Y函数,则该操作也会立即执行。
那么,这是否意味着性能下降是由X&Y函数引起的,除了,不是吗?我糊涂了。
更新#2:
如果我将X和Y移出查询,将它们放在外部查询中,然后将ROWNUM添加到内部查询中,则速度会更快(16秒-更新):
SELECT
ROWNUM
,ROAD_ID
,VERTEX_INDEX
,SDE.ST_X(ST_POINT) AS X
,SDE.ST_Y(ST_POINT) AS Y
FROM
(
SELECT
ROWNUM
,a.ROAD_ID
,b.NUMBERS VERTEX_INDEX
,SDE.ST_PointN(a.SHAPE, b.NUMBERS) AS ST_POINT
FROM ENG.ROAD a
CROSS JOIN ENG.NUMBERS b
WHERE b.NUMBERS <= SDE.ST_NumPoints(a.SHAPE)
)
--removed to do explain plan: ORDER BY ROAD_ID, VERTEX_INDEX
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5996 | 322K| | 262 (1)| 00:00:01 |
| 1 | COUNT | | | | | | |
| 2 | VIEW | | 5996 | 322K| | 262 (1)| 00:00:01 |
| 3 | COUNT | | | | | | |
| 4 | MERGE JOIN | | 5996 | 1545K| | 262 (1)| 00:00:01 |
| 5 | INDEX FULL SCAN | R23715_SDE_ROWID_UK | 30 | 90 | | 1 (0)| 00:00:01 |
|* 6 | SORT JOIN | | 3997 | 1018K| 2392K| 261 (1)| 00:00:01 |
| 7 | TABLE ACCESS FULL| ROAD | 3997 | 1018K| | 34 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
" 6 - access(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
" filter(""B"".""NUMBERS""<=""SDE"".""ST_NumPoints""(""A"".""SHAPE""))"
贾斯汀·凯夫(Justin Cave)在这里解释了为什么ROWNUM有助于提高性能:为什么在查询中添加ROWNUM可以提高性能?
尽管此性能改进不错,但还不够好。而且我不禁以为我仍然不完全了解查询的工作方式或查询速度如此缓慢的原因。
问题仍然存在:是否有更好的方法?