SQL查询从多行获取最新信息 - 太慢了

时间:2014-04-04 09:09:31

标签: sql performance maximo

我已经为SRSS报告编写了一个查询,该报告应该从maximo中检索项目列表。

它包括库存中的商品数量,是否有收货和/或发货日期(如果是,那么最新日期是什么)以及当时的单位成本。

虽然它返回了我想要的东西,但它运行得非常缓慢,以至于在报告中使用它时似乎永远不会加载。 5000行需要21秒(并且在maximo中已经有> 100k的事务!)。如何退回单位成本以使其更快?它在没有单位成本线的情况下快速运行。

查询

select top 5000 item.commoditygroup, item.itemnum, item.description, item.commodity, inventory.location, inventory.siteid,
(select sum(curbal) from invbalances where item.itemnum = invbalances.itemnum group by itemnum) CurrentBalance,
(select max(Convert(varchar(10), matrectrans.transdate, 103)) from matrectrans 
where item.itemnum = matrectrans.itemnum and matrectrans.issuetype='RECEIPT') ReceivedDate,
(Select m1.unitcost from matrectrans m1 
where m1.transdate = (select max(m2.transdate)from matrectrans m2 where item.itemnum = m2.itemnum and m2.issuetype='RECEIPT' and linecost <> 0)) RecievedUnitCost,
(select max(Convert(varchar(10), matusetrans.transdate, 103)) from matusetrans 
where item.itemnum = matusetrans.itemnum and matusetrans.issuetype='ISSUE') IssueDate,
(Select m3.unitcost from matusetrans m3 
where m3.transdate = (select max(m4.transdate)from matusetrans m4 where item.itemnum = m4.itemnum and m4.issuetype='ISSUE' and linecost <> 0)) IssuedUnitCost
from item, inventory
where item.itemnum = inventory.itemnum

由于

3 个答案:

答案 0 :(得分:1)

对于每个项目包含所有子查询的dbms,还有很多工作要做。所以不要指望这很快。我想你已经确定表中有适当的索引。

因此,我认为加快这一速度的唯一机会是让dbms尽可能快地找到这5000条记录。实际上,您不会使用order by,因此您只需获得5000个随机库存。对于结果列表中的一个项目,您可能会获得所有库存或仅包含其中一些库存,它们都是随机的。

知道了,您可以选择5000个随机库存,只有在找到这些库存后才能加入项目:

select 
  item.commoditygroup, 
  item.itemnum, 
  item.description, 
  item.commodity, 
  inv5000.location, 
  inv5000.siteid, 
  ...
from (select top 5000 itemnum, location, siteid, from inventory) inv5000
inner join item on item.itemnum = inv5000.itemnum;

也许这会改变一些事情。也许不吧。祝你好运!

答案 1 :(得分:0)

对于您的unitcost子选择,请改用matrectransid和matusetransid。这些ID字段已编入索引,可以加快查询速度:

(Select m1.unitcost from matrectrans m1 where m1.matrectransid =
(select max(m2.matrectransid) from matrectrans m2 
where item.itemnum = m2.itemnum and m2.issuetype='RECEIPT' and linecost <> 0))
ReceivedUnitCost

(Select m3.unitcost from matusetrans m3 where m3.matusetransid = 
(select max(m4.matusetransid) from matusetrans m4 
where item.itemnum = m4.itemnum and m4.issuetype='ISSUE' and linecost <> 0)) 
IssuedUnitCost

在我的数据库中,更大的ID值与更新的transdate相关。您可以使用Lag Function验证自己:

这适用于Oracle,但SQL Server也具有LAG功能。

select matusetransid, 
to_char(transdate, 'DD-MON-YYYY HH24:MI:SS.ss') transdate,  
LAG (to_char(transdate, 'DD-MON-YYYY HH24:MI:SS.ss'),1) 
over (order by transdate desc) as prev_transdate, 
(case when transdate > LAG (transdate,1) over (ORDER BY matusetransid desc) 
then 1 else 0 end) as test 
from matusetrans
where 4 = 1
order by matusetransid desc;

如果上述查询返回任何行,则表示某些数据不按顺序排列(插值)。

关于结果集的旁注:您选择的是inventory.location和inventory.siteid,但您的子选择与这些字段不匹配。如果您的itemnum只属于一个siteid和location(库房),那么当前查询应该没问题。否则,您的结果可能不准确。

答案 2 :(得分:0)

谢谢大家 - 我最终得到了这个查询,它运行得更快(它在2秒内获得10000条记录)

select distinct inventory.itemnum, item.commodity, item.commoditygroup, inventory.siteid, inventory.location, inventory.itemsetid, 
item
.description as itemDesc, inventory.issueunit as iUnit,


(select max(actualdate) from matusetrans 

where issuetype in (select value from synonymdomain where domainid = 'ISSUETYP' and maxvalue = 'ISSUE') 

and siteid=inventory.siteid and storeloc=inventory.location and itemsetid=inventory.itemsetid and itemnum=inventory.itemnum) as useTransDate,


(select max(actualdate) from matrectrans 

where issuetype in (select value from synonymdomain where domainid = 'ISSUETYP' and maxvalue = 'RECEIPT')

and siteid=inventory.siteid and tostoreloc=inventory.location and itemsetid=inventory.itemsetid and itemnum=inventory.itemnum 

) as recTransDate 
from

inventory inner join item on inventory.itemsetid = item.itemsetid and inventory.itemnum = item.itemnum 
where

item.itemtype in ( select value from synonymdomain where domainid = 'ITEMTYPE' and maxvalue in ('ITEM') ) 

and inventory.status not in ( select value from synonymdomain where domainid='ITEMSTATUS' and maxvalue in ('OBSOLETE') )