我遇到以下查询的性能问题,我想获得一些有关销售线和每个销售线的信息,我想知道最后一个日期是否已收到库存:
SELECT XAL_SUPERVISOR.SALESTABLE.SALESNUMBER, XAL_SUPERVISOR.SALESTABLE.DEBTORACCOUNT, XAL_SUPERVISOR.SALESTABLE.DELIVERYNAME,
XAL_SUPERVISOR.SALESTABLE.DELIVERYADDRESS3, XAL_SUPERVISOR.SALESTABLE.REQUISNUMBER, XAL_SUPERVISOR.SALESTABLE.CUSTOMERREF,
XAL_SUPERVISOR.SALESTABLE.ROUTE, XAL_SUPERVISOR.SALESTABLE.ROUTENUMBER, XAL_SUPERVISOR.SALESTABLE.CMPVWSTATUS,
XAL_SUPERVISOR.SALESTABLE.CMPLOGISTIEK, XAL_SUPERVISOR.SALESTABLE.USVEHICLE, XAL_SUPERVISOR.SALESTABLE.ELCSALSTCALL,
XAL_SUPERVISOR.SALESTABLE.ELCSALSTOK, XAL_SUPERVISOR.SALESTABLE.ELCEDICODE, XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER,
XAL_SUPERVISOR.STOCKTABLE.ITEMNAME, XAL_SUPERVISOR.SALESTRANS.QTYORDERED, XAL_SUPERVISOR.SALESTRANS.STOCKLOC AS REGELLOC,
XAL_SUPERVISOR.STOCKTABLE.STOCKLOC AS STDLOC, XAL_SUPERVISOR.SALESTABLE.DELIVERYDATE, XAL_SUPERVISOR.SALESTABLE.DATASET,
XAL_SUPERVISOR.SALESTABLE.CMPCORRECTIE, XAL_SUPERVISOR.SALESTRANS.ELCORGQTYORDERED AS ORG_BESTELD,
XAL_SUPERVISOR.STOCKTABLE.CMPVERVALLEN,
(SELECT (SUM(STS.ENTEREDQTY) + SUM(STS.RECEIVED) - SUM(STS.DRAWN))
FROM XAL_SUPERVISOR.STOCKSUM STS
WHERE STS.ITEMNUMBER = XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER AND STS.DATASET = 'CMP'
GROUP BY STS.ITEMNUMBER) AS VOORRAAD,
(SELECT SUM(STS.ORDERED)
FROM XAL_SUPERVISOR.STOCKSUM STS
WHERE STS.ITEMNUMBER = XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER AND STS.DATASET = 'CMP'
GROUP BY STS.ITEMNUMBER) AS BESTELD,
(SELECT SUM(STS.RESERVPHYSICAL)
FROM XAL_SUPERVISOR.STOCKSUM STS
WHERE STS.ITEMNUMBER = XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER AND STS.DATASET = 'CMP'
GROUP BY STS.ITEMNUMBER) AS GERESERVEERD,
(SELECT DDT.QTY
FROM XAL_SUPERVISOR.DEBDLVTRANS DDT
WHERE DDT.TRANSID = XAL_SUPERVISOR.SALESTRANS.TRANSID AND DDT.DATASET = 'CMP') AS PAKBONAANTAL,
(SELECT DIT.QTY
FROM XAL_SUPERVISOR.DEBINVTRANS DIT
WHERE DIT.TRANSID = XAL_SUPERVISOR.SALESTRANS.TRANSID AND DIT.DATASET = 'CMP') AS FACTUURAANTAL,
(SELECT MAX(ST.DATEPHYSICAL)
FROM XAL_SUPERVISOR.STOCKTRANS ST
WHERE ST.ITEMNUMBER = XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER AND ST.DATASET = 'CMP' AND ST.StatusInFlow < 3 AND ST.DCType = 2)
AS LTSTGELEVERD
FROM XAL_SUPERVISOR.SALESTABLE, XAL_SUPERVISOR.SALESTRANS, XAL_SUPERVISOR.STOCKTABLE
WHERE XAL_SUPERVISOR.SALESTABLE.DATASET = XAL_SUPERVISOR.SALESTRANS.DATASET AND
XAL_SUPERVISOR.SALESTABLE.SALESNUMBER = XAL_SUPERVISOR.SALESTRANS.SALESNUMBER AND
XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER = XAL_SUPERVISOR.STOCKTABLE.ITEMNUMBER AND
XAL_SUPERVISOR.SALESTRANS.DATASET = XAL_SUPERVISOR.STOCKTABLE.DATASET AND (XAL_SUPERVISOR.SALESTABLE.DELIVERYDATE = :Leverdatum) AND
(XAL_SUPERVISOR.SALESTABLE.DATASET = 'CMP') AND (XAL_SUPERVISOR.SALESTABLE.CMPCORRECTIE = 0)
这部分减慢速度(没有它在<10秒内运行):
(SELECT MAX(ST.DATEPHYSICAL)
FROM XAL_SUPERVISOR.STOCKTRANS ST
WHERE ST.ITEMNUMBER = XAL_SUPERVISOR.SALESTRANS.ITEMNUMBER AND ST.DATASET = 'CMP' AND ST.StatusInFlow < 3 AND ST.DCType = 2)
AS LTSTGELEVERD
当我在SQL中运行它时,我看到它获取主查询然后暂停很长时间才能获取上面的子查询?
答案 0 :(得分:1)
如果从.net或coldfusion等应用程序运行此查询,则可以单独运行查询并将其加入应用程序中。使用.net,它将成为DataTable和coldfusion的linq,它将是查询查询。
您可以在存储过程中执行相同的操作。使用子查询中的数据填充临时表,然后将其连接到临时表。
虽然这些事情都是违反直觉的,甚至可能代表最坏的做法,但有时它们适合当前的情况。
答案 1 :(得分:1)
SELECT子句中的子查询往往表现不佳一种改进方法是使用内联视图或WITH子句来计算每个ITEMNUMBER的最大值,然后加入它。
WITH datephysical_max as
(SELECT Max(ST.datephysical) max_ , ST.itemnumber
FROM xal_supervisor.stocktrans ST
WHERE
AND ST.dataset = 'CMP'
AND ST.statusinflow < 3
AND ST.dctype = 2
GROUP BY )
SELECT
....,
st.LTSTGELEVERD
FROM xal_supervisor.salestable
inner join xal_supervisor.salestrans
ON xal_supervisor.salestable.dataset =
xal_supervisor.salestrans.dataset
AND xal_supervisor.salestable.salesnumber =
xal_supervisor.salestrans.salesnumber
AND xal_supervisor.salestrans.itemnumber =
xal_supervisor.stocktable.itemnumber
inner join xal_supervisor.stocktable
ON xal_supervisor.salestrans.dataset =
xal_supervisor.stocktable.dataset
INNER JOIN datephysical_max st
ON ST.itemnumber = xal_supervisor.salestrans.itemnumber
WHERE ( xal_supervisor.salestable.deliverydate = :Leverdatum )
AND ( xal_supervisor.salestable.dataset = 'CMP' )
AND ( xal_supervisor.salestable.cmpcorrectie = 0 )
答案 2 :(得分:1)
您可以尝试以下几种方法:
第四个和第五个子查询只获得一个标量值,因此可以将它们放入查询的主体中。看起来您在这里使用子查询来避免使用LEFT JOIN
。
可以使用公用表表达式(CTE)组合第一,第二,第三和第六子查询,也称为Oracle WITH
子句。与其他子查询值一样,现在必须使用LEFT JOIN
合并这些值。
此外,如果您使用ANSI连接语法,这会更容易。这是答案(尽管注意我已经遗漏了很多“旁观者”列,所以它会有点紧凑;如果这个解决方案适合你,你可以添加它们):
WITH StkSum AS (
SELECT
STS.ITEMNUMBER,
SUM(STS.ENTEREDQTY) + SUM(STS.RECEIVED) - SUM(STS.DRAWN) AS VOORRAAD,
SUM(STS.ORDERED) AS BESTELD,
SUM(STS.RESERVPHYSICAL) AS GERESERVEERD,
MAX(ST.DATEPHYSICAL) AS LTSTGELEVERD
FROM XAL_SUPERVISOR.STOCKSUM STS
INNER JOIN XAL_SUPERVISOR.STOCKTRANS ST ON STS.ITEMNUMBER = ST.ITEMNUMBER
WHERE STS.DATASET = 'CMP'
AND ST.DATASET = 'CMP'
AND ST.StatusInFlow < 3
AND ST.DCType = 2
)
SELECT
XAL_SUPERVISOR.SALESTABLE.SALESNUMBER,
... all those SALESTABLE and SALESTRANS and STOCKTABLE columns ...,
StkSum.VOORRAAD,
StkSum.BESTELD,
StkSum.GERESERVEERD,
NVL(XAL_SUPERVISOR.DEBDLVTRANS.QTY, 0) AS PAKBONAANTAL,
NVL(XAL_SUPERVISOR.DEBINVTRANS.QTY, 0) AS FACTUURAANTAL,
StkSum.LTSTGELEVERD
FROM XAL_SUPERVISOR.SALESTABLE
INNER JOIN XAL_SUPERVISOR.SALESTRANS ON
SalesTable.DataSet = SalesTrans.DataSet AND
SalesTable.SalesNumber = SalesTrans.SalesNumber
INNER JOIN XAL_SUPERVISOR.STOCKTABLE ON
SalesTrans.ItemNumber = StockTable.ItemNumber AND
SalesTrans.DataSet = StockTable.DataSet
LEFT OUTER JOIN StkSum ON StkSum.ITEMNUMBER = SalesTrans.ITEMNUMBER
LEFT OUTER JOIN XAL_SUPERVISOR.DEBDLVTRANS DDT ON DDT.TRANSID = SalesTrans.TRANSID
LEFT OUTER JOIN XAL_SUPERVISOR.DEBINVTRANS DIT ON DIT.TRANSID = SalesTrans.TRANSID
WHERE
(XAL_SUPERVISOR.SALESTABLE.DELIVERYDATE = :Leverdatum) AND
(XAL_SUPERVISOR.SALESTABLE.DATASET = 'CMP') AND
(XAL_SUPERVISOR.SALESTABLE.CMPCORRECTIE = 0) AND
DDT.DATASET = 'CMP' AND
DIT.DATASET = 'CMP'
最后,请注意由于表格和列数和条件的绝对数量,如果上面的查询是100%正确,我会感到震惊。我尽我所能,但我最好的可能还不够好:)可能需要Tweakage。
答案 3 :(得分:1)
你的选择会减慢查询的速度,使得速度变慢:
数学(小于)可以不使用案例索引。考虑
如果列表很小,则更改为列表
如果您没有如下索引,那么它会很慢
一个打开(ST.item_number,ST.dataset,ST.status_in_flow,ST.dctype) 一个在XAL_SUPERVISOR(itemNumber)上 一个on datephysical可以被max使用,因为它会导致order by。
如果不使用索引,原因有很多。数学在where子句中,如果大行数,则明确考虑第1项,因此将使用索引。此外,如果列可以为null,to_upper等,则可以使用基于函数的索引。