Функция Oracle Spatial SDO_CS.Transform(value) работает очень медленно

У меня есть собственное представление, которое запрашивает пространственные данные из столбцов геометрии и извлекает значения широты/долготы. Однако процесс извлечения очень медленный и занимает от 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.

Любые советы по получению такого типа представлений/данных приветствуются. Или любые другие пространственные функции, которые я могу использовать для более быстрого достижения этого?


person reggie    schedule 03.09.2015    source источник
comment
ПОЧЕМУ ЗА ВОПРОС НЕ ПРОГОЛОСОВАЛИ? может ли пользователь, который проголосовал против, прокомментировать причину?   -  person reggie    schedule 04.09.2015
comment
Если в PolePoint и PoleDetailPoint нет перекрытия, вы можете использовать UNION ALL вместо UNION, тогда базе данных не придется различать результаты.   -  person Sentinel    schedule 04.09.2015
comment
Вам действительно нужно Union? почему вы не используете union all?   -  person Florin Ghita    schedule 09.09.2015
comment
если это для отчетности, почему бы просто не создать материализованное представление? Обновляйте его один раз в день и добавляйте к нему индекс или два, и вы можете запросить его разделение по лизу.   -  person tbone    schedule 09.09.2015
comment
У меня нет времени и данных, чтобы возиться с ним, но я бы попытался намекнуть первому оператору на использование хэша между основной таблицей и скрытой таблицей, которая поддерживает вложенную таблицу, используемую для пространственного столбца. Я подозреваю, что NL использует индекс вложенной таблицы. Не могли бы вы опубликовать план выполнения?   -  person Florin Ghita    schedule 10.09.2015
comment
Как именно вы запрашиваете это представление? И, как предположил Флорин, план объяснения был бы полезен. Создайте такой: explain plan for select * from PoleData;, а затем select * from table(dbms_xplan.display);. Производительность может не иметь ничего общего с SDO, это может быть просто плохой план выполнения.   -  person Jon Heller    schedule 14.09.2015


Ответы (2)


Попробуйте использовать 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 записей, по одной для каждой из 25 возможных комбинаций T и T2 для этой 5 вершины 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;
person Sentinel    schedule 15.09.2015

Вы пытались переместить приведение к элементам таблицы в предложение 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)

С уважением Олафур

person Olafur Tryggvason    schedule 15.09.2015
comment
Вы не можете вывести элементы приведения к таблице с помощью предложения with, поскольку они зависят от таблицы полюсов. Обратите внимание на ссылки p.g3e_geometry. - person Sentinel; 15.09.2015
comment
Ах, да, конечно. Я вижу это сейчас. Но это объясняет, почему он такой медленный. table(sdo_util.getvertices(...)) запускается 2 раза для каждой отдельной строки в polepoint и 2 раза для каждой отдельной строки в poledetailpoint. - person Olafur Tryggvason; 15.09.2015