英文:
How can I make this nested query mess faster?
问题
我正在从我的SQL Server数据库查询外部Oracle数据库。我知道,没有WHERE子句,大约在55秒内返回约190,000条记录。添加WHERE子句会导致返回时间从30秒到2.5分钟不等。我知道是最后一个内连接(嵌套查询)导致的,因为没有它,返回时间只需大约2秒,但我不知道如何修复它。我在下面发布了原始查询。我尝试将第一个表作为JOBs的子查询,这样我只连接我需要其他信息的jobs,但这没有帮助。
这都是通过一个存储过程调用的。@jobNumber是该存储过程的参数。
英文:
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+'''''')
答案1
得分: 1
你或许应该使用CROSS APPLY来获取零件数量的状态,而不是创建行号。例如:
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
-- SQL Server语法
CROSS APPLY
(
SELECT TOP 1 Status
FROM EXTERNALDB.STATUSES
WHERE PART_NUM = t3.PART_NUM
) T6
-- 或许在Oracle中也能工作
CROSS APPLY
(
SELECT Status
FROM EXTERNALDB.STATUSES
WHERE PART_NUM = t3.PART_NUM
FETCH FIRST 1 ROWS ONLY
) T6
WHERE t3.JOB = ''' + @jobNumber + '''')
有关Oracle中的TOP的参考链接:https://blogs.oracle.com/sql/post/how-to-select-the-top-n-rows-per-group-with-sql-in-oracle-database
有关Oracle中的CROSS APPLY的参考链接:https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9530807800346558418
英文:
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
答案2
得分: 1
最高效的调用链接服务器的方法是通过以下方式:
EXECUTE (...) AT [LINKED_SERVER]
这样查询的整个执行将在远程服务器上进行。SQL Server 只会输出其结果。
供参考:SQL Server: Execute At LinkedServer
第二个好处是参数传递更加清晰。无需拼接字符串。请查看下面的 SQL 示例。
SQL
EXECUTE (N'SELECT
t1.SERIAL,
t3.PART_NUM,
...
FROM EXTERNALDB.STATUSES t4) t5
WHERE RN = 1) t6 ON t3.PART_NUM = PART
WHERE t3.JOB = ?', @jobNumber) AT [externaldb];
英文:
The most performant way to call a linked server is via
EXECUTE (...) AT [LINKED_SERVER]
That way the entire execution of a query will happen on the remote server. SQL Server will just output the result of it.
For the reference: SQL Server: Execute At LinkedServer
The 2nd benefit is that parameters passing is much cleaner. No need to concatenate strings. Check it out below SQL.
SQL
EXECUTE (N'SELECT
t1.SERIAL,
t3.PART_NUM,
...
FROM EXTERNALDB.STATUSES t4) t5
WHERE RN = 1) t6 ON t3.PART_NUM = PART
WHERE t3.JOB = ?',
@jobNumber) AT [externaldb];
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论