Вопрос:
У меня есть пространственная таблица (дорожные линии), хранящаяся с использованием SDE.ST_GEOMETRY
пользовательского типа данных ESRI в базе геоданных 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 вершин на линию)
- ДОРОГ имеет 3,997 линий
- ЧИСЛО имеет 30 строк (порядковые номера, начинающиеся с 1)
- Результирующий набор содержит 17 536 строк
Тем не менее, производительность плохая (40 секунд), и я не могу не думать - есть ли более элегантный способ сделать это? Для меня использование таблицы чисел и перекрестного соединения кажется небрежным подходом. Есть ли способ лучше?
Условия Layman будут оценены; Я парень из общественных работ, а не администратор.
Обновление № 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""))"
Джастин Кейв объясняет, почему ROWNUM помогает повысить производительность: почему добавление ROWNUM в запрос повышает производительность?
Хотя это улучшение производительности и хорошо, но пока недостаточно. И я не могу не думать, что до сих пор не до конца понимаю, как работает запрос или почему он такой медленный, как он есть.
Вопрос все еще стоит: есть ли лучший путь?