質問:
ESRIのユーザー定義データタイプを使用してOracle 12c ジオデータベースに格納された空間テーブル(道路線)SDE.ST_GEOMETRY
があります。最終的にそれらの座標にアクセスして更新できるように、線の頂点をリストします。SDO_GEOMETRY / Oracle Locatorを使用している場合は、関数を使用し
ます。しかし、私はSDO_GEOMETRY / Oracle Locatorを使用しておらず、に同等の関数はありません。唯一の機能私は頂点に関係することを見つけることができますがありますと。SDO_UTIL.GETVERTICES
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個の頂点があります(1行あたりの平均は4.38個の頂点)
- ROADSには3,997行あります
- NUMBERSには30行あります(1から始まる連番)
- 結果セットには17,536行あります
ただし、パフォーマンスが悪い(40秒)ので、考えざるを得ません。これを行うためのよりエレガントな方法はありますか?私にとって、数値テーブルとクロス結合を使用することは、ずさんなアプローチのように思えます。もっと良い方法はありますか?
レイマンの条件をいただければ幸いです。私はDBAではなく、Public Worksの人です。
アップデート#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を追加するとパフォーマンスが向上するのはなぜですか?
このパフォーマンスの改善は良好ですが、まだ十分ではありません。そして、どうしようもないのですが、クエリがどのように機能するか、なぜクエリが遅いのか、まだ完全には理解していません。
問題はまだ残っています:より良い方法はありますか?