Search code examples
sql-serveroracle-databaseopenquery

How can I make this nested query mess faster?


I'm querying an external Oracle database from my SQL Server database. I know, without the WHERE clause it returns about 190,000 records in about 55 seconds. The addition of the where clause causes the return to take anywhere from 30 seconds to 2.5 minutes. I know it's the last inner join (the nested queries) because without it the return only takes about 2 seconds, but I have no idea how I can fix it. I'm posting the original query below. I've tried making the first table a subquery of the JOBs so I'm only joining on the jobs I need the other info on, but that didn't help.

This is all called with a procedure. @jobNumber is a parameter of that procedure

SELECT * FROM OPENQUERY(externaldb,'SELECT
t1.SERIAL,
t3.PART_NUM,
t2.SUFFIX,
t3.JOB,
t2.DESC,
t2.MODEL,
t2.QTY,
t2.UNIT,
t2.LOCATION,
t6.STATUS,
t1.DESTINATION,
t1.ORDER,
t1.PURCHASER,
t1.PHONE,
t1.CUSTOMER_ID
FROM EXTERNALDB.SERIALS t1
INNER JOIN EXTERNALDB.DELIVERIES t2 ON t1.SERIAL = t2.SERIAL
INNER JOIN EXTERNALDB.DESC t3 ON t2.PART_NUM = t3.PART_NUM
INNER JOIN (SELECT PART, STATUS
            FROM (SELECT
                       t4.SUFFIX,
                       t4.STATUS_TYPE,
                       t4.STATUS_DATE,
                       t4.ID,
                       t4.PART_NUM PART,
                       t4.STATUS,
                       ROW_NUMBER()
                            OVER (PARTITION BY t4.PART_NUM
                            ORDER BY
                                 t4.SUFFIX,
                                 t4.STATUS_TYPE,
                                 t4.STATUS_DATE,
                                 t4.ID) RN
                   FROM EXTERNALDB.STATUSES t4) t5
                   WHERE RN = 1) t6 ON t3.PART_NUM = PART
WHERE t3.JOB = '''''+@jobNumber+'''''')

Solution

  • Maybe instead of create rownumber you should use cross apply to get the status of the number of part. for example

    SELECT * FROM OPENQUERY(externaldb,'SELECT
    t1.SERIAL,
    t3.PART_NUM,
    t2.SUFFIX,
    t3.JOB,
    t2.DESC,
    t2.MODEL,
    t2.QTY,
    t2.UNIT,
    t2.LOCATION,
    t6.STATUS,
    t1.DESTINATION,
    t1.ORDER,
    t1.PURCHASER,
    t1.PHONE,
    t1.CUSTOMER_ID
    FROM EXTERNALDB.SERIALS t1
    INNER JOIN EXTERNALDB.DELIVERIES t2 ON t1.SERIAL = t2.SERIAL
    INNER JOIN EXTERNALDB.DESC t3 ON t2.PART_NUM = t3.PART_NUM
    -- sintaxis sql server
    CROSS APPLY
    (
      SELECT TOP 1 Status
      From EXTERNALDB.STATUSES
      Where PART_NUM = t3.PART_NUM
    ) T6
    -- maybe works in oracle
    CROSS APPLY
    (
      SELECT Status
      From EXTERNALDB.STATUSES
      Where PART_NUM = t3.PART_NUM
      FETCH first 1 rows only
    ) T6
    WHERE t3.JOB = '''''+@jobNumber+'''''')
    

    Reference about top in oracle https://blogs.oracle.com/sql/post/how-to-select-the-top-n-rows-per-group-with-sql-in-oracle-database

    Reference about cross apply in oracle https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9530807800346558418