Search code examples
oracle-databasegeometryspatial-queryspatial-index

Oracle Spatial function SDO_CS.Transform(value) results really slow


I have a custom view which queries spatial data from geometry columns and extracts latitude/longtitude values. However, the retrieval process is really slow, and takes upto 5 to 10 mins for the view data to be retrieved.

Here is my view:

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;

The G3E_GEOMETRY column is of SDO_GEOMETRY type. PolePoint table has 1,310,629 rows while PoleDetailPoint has 100. The data in this tables are updated on a daily basis, while the view is used for reporting purposes.

I tried rebuilding the spatial index using the status=cleanup parameter. But that didn't make any difference.

Our version is Oracle 11.2.0.3.

Any tips on retrieving such type of views/data appreciated. Or any other spatial functions that I can use to achieve this faster?


Solution

  • Try using UNION ALL instead of 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;
    

    Another potential source of performance degradation comes from the fact that you are using two calls to SDO_UTIL.GET_VERTICES one directly on P.G3E_GEOMETRY and the other on a transform of P.G3E_GEOMETRY you will essentially have a cross product of the two vertices lists, so for example if a particular P.G3E_GEOMETRY contains 5 vertices, then you will end up with 5 * 5 records one for each of the 25 possible combinations of T and T2 for that 5 vertex P.G3E_GEOMETRY. I don't know if the vertex order is maintained by the SDO_CS.TRANSFORM function, but if it is, you could improve your performance by adding the and t1.id = t2.id predicate to each half of your query:

    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;