我有这个更新远程表的sql update语句。有什么办法可以优化/加速这段代码吗?它作为存储过程的一部分运行。
DECLARE @WIP Table(Item varchar(25), WIP int)
--Get Work In Progress Numbers
INSERT INTO @WIP
select (UPC.ItemPrefix + '-' + UPC.ItemCode) As Item, SUM(PO.Quantity) As WIP
--into #WIP
from [NCLGS].[dbo].[AL_ItemUPCs] UPC
INNER JOIN al_PO PO ON PO.UPCID = UPC.UPCID
where PO.status in ('Assigned', 'New', 'UnAssigned', 'WaitingForFile')
Group by (UPC.ItemPrefix + '-' + UPC.ItemCode)
--SLOW PART, takes over 17 minutes
UPDATE [Server].[Database].[dbo].[Item]
SET QtyOnHand = IH.QtyOnHand,
QtyWorkInProgress = W.WIP
FROM Avanti_InventoryHeader IH
INNER JOIN [Server].[Database].[dbo].[Item] I ON I.ItemNumber = IH.ItemNumber
LEFT JOIN @WIP W ON IH.ItemNumber = W.Item
WHERE isnumeric(left(IH.ItemNumber, 2)) = 0
答案 0 :(得分:1)
我过去遇到过类似的问题,我不得不使用动态SQL来提高性能。
我发现当我使用远程表加入本地临时表时,SQL将所有数据带到本地服务器,然后过滤where语句中的内容。
在这种情况下,我会尝试在动态查询中使用SELECT UNION ALL将整个变量表@WIP作为嵌套表传递。
我说的是这样的事情:
DECLARE @WIP Table(Item varchar(25), WIP int)
--Get Work In Progress Numbers
INSERT INTO @WIP
select (UPC.ItemPrefix + '-' + UPC.ItemCode) As Item, SUM(PO.Quantity) As WIP
--into #WIP
from [NCLGS].[dbo].[AL_ItemUPCs] UPC
INNER JOIN al_PO PO ON PO.UPCID = UPC.UPCID
where PO.status in ('Assigned', 'New', 'UnAssigned', 'WaitingForFile')
Group by (UPC.ItemPrefix + '-' + UPC.ItemCode)
declare @SQL VARCHAR(MAX)
set @SQL = '
UPDATE [Server].[Database].[dbo].[Item]
SET QtyOnHand = IH.QtyOnHand,
QtyWorkInProgress = W.WIP
FROM Avanti_InventoryHeader IH
INNER JOIN [Server].[Database].[dbo].[Item] I
ON I.ItemNumber = IH.ItemNumber
LEFT JOIN ('
select @SQL = @SQL + 'select '''+w.Item+''' as Item,
'''+cast( w.WIP as varchar(50))+''' as WIP union all '
from @WIP W
set @SQL = @SQL + ' select NULL,0 ) W
ON IH.ItemNumber = W.Item
WHERE isnumeric(left(IH.ItemNumber, 2)) = 0 '
PRINT @SQL
它看起来不是很整洁,但它可能对你有效。
答案 1 :(得分:1)
在尝试连接之前,我首先尝试将项目加载到本地表变量中。
DECLARE @WIP Table ( Item varchar(25), WIP int )
--Get Work In Progress Numbers
INSERT INTO @WIP
select ( UPC.ItemPrefix + '-' + UPC.ItemCode ) As Item,
SUM(PO.Quantity) As WIP
--into #WIP
from [NCLGS].[dbo].[AL_ItemUPCs] UPC
INNER JOIN al_PO PO ON PO.UPCID = UPC.UPCID
where PO.status in ( 'Assigned', 'New', 'UnAssigned',
'WaitingForFile' )
Group by ( UPC.ItemPrefix + '-' + UPC.ItemCode )
DECLARE @Item TABLE (ItemNumber INT PRIMARY KEY, QtyOnHand INT)
SELECT ItemNumber, QtyOnHand
FROM [Server].[Database].[dbo].[Item]
--SLOW PART, takes over 17 minutes
UPDATE [Server].[Database].[dbo].[Item]
SET QtyOnHand = IH.QtyOnHand,
QtyWorkInProgress = W.WIP
FROM Avanti_InventoryHeader IH
INNER JOIN @item I ON I.ItemNumber = IH.ItemNumber
LEFT JOIN @WIP W ON IH.ItemNumber = W.Item
WHERE isnumeric(left(IH.ItemNumber, 2)) = 0
此外,您可以考虑通过从表变量中删除未更新的记录来进一步限制更新,并仅将更新的记录连接到链接服务器。
DECLARE @Item TABLE
(
ItemNumber INT PRIMARY KEY,
QtyOnHand INT,
updated BIT DEFAULT ( 0 ),
WIP int
)
SELECT ItemNumber,
QtyOnHand
FROM [Server].[Database].[dbo].[Item]
UPDATE i
SET i.QtyOnHand = ih.QtyOnHand,
updated = 1
FROM @item i
INNER JOIN Avanti_InventoryHeader IH ON I.ItemNumber = IH.ItemNumber
LEFT JOIN @WIP W ON IH.ItemNumber = W.Item
WHERE isnumeric(left(IH.ItemNumber, 2)) = 0
DELETE FROM @item WHERE updated = 0
UPDATE I
SET QtyOnHand = IH.QtyOnHand,
QtyWorkInProgress = IH.WIP
FROM [Server].[Database].[dbo].[Item] I
INNER JOIN @item IH ON I.ItemNumber = IH.ItemNumber
答案 2 :(得分:0)
尝试在此存储过程调用的远程服务器上创建存储过程。
在远程存储过程中,将您需要的数据提取到临时表中。然后在远程服务器上执行UPDATE / JOIN。
根据我的经验,尝试在链接服务器上进行连接可能会非常慢......在进行任何连接之前,通常可以更快地在一台服务器上获取所有必需的数据。
答案 3 :(得分:0)
我找出了查询的真正问题,它正在更新数千条记录,即使这些记录没有改变。因此,我查询了已更改的记录,将其保存在表变量中,并仅更新已更改的记录。整个程序(不仅仅是这部分)从16分44秒到1分26秒。
--BEGIN EXPERIMENTAL ITEM UPDATE SECTION
DECLARE @WIP Table(Item varchar(25), WIP int)
--Get Work In Progress Numbers
INSERT INTO @WIP
select (UPC.ItemPrefix + '-' + UPC.ItemCode) As Item, SUM(PO.Quantity) As WIP
--into #WIP
from [NCLGS].[dbo].[AL_ItemUPCs] UPC
INNER JOIN al_PO PO ON PO.UPCID = UPC.UPCID
where PO.status in ('Assigned', 'New', 'UnAssigned', 'WaitingForFile')
Group by (UPC.ItemPrefix + '-' + UPC.ItemCode)
Declare @Remote Table(Item varchar(25), QtyOnHand int, WIP int)
INSERT INTO @REMOTE
Select ItemNumber, QtyOnHand, QtyWorkInProgress
from [BMPR.COM].[NCL-CustomerPortal].[dbo].[Item]
DECLARE @ItemsToUpdate Table (Item varchar(50))
INSERT INTO @ItemsToUpdate
Select R.Item
From @Remote R
Inner join Avanti_InventoryHeader IH ON R.Item = IH.ItemNumber
LEFT JOIN @WIP W ON R.Item = W.Item
Where R.QtyOnHand <> IH.QtyOnHand
OR R.WIP <> W.WIP
--Select * from @ItemsToUpdate
UPDATE [BMPR.COM].[NCL-CustomerPortal].[dbo].[Item]
SET QtyOnHand = IH.QtyOnHand,
QtyWorkInProgress = W.WIP
FROM Avanti_InventoryHeader IH
INNER JOIN [BMPR.COM].[NCL-CustomerPortal].[dbo].[Item] I ON I.ItemNumber = IH.ItemNumber
LEFT JOIN @WIP W ON IH.ItemNumber = W.Item
WHERE I.ItemNumber in ( Select * from @ItemsToUpdate )
--END EXPERIMENTAL ITEM UPDATE SECTION
对此方法有何评论?
答案 4 :(得分:-1)
PostgreSQL的UPDATE中只有一个ONLY子句,它只会更新上面提到的表。否则它会尝试更新您加入的所有表,这可能是瓶颈所在。你使用什么类型的SQL?如果是Postgres,可能还有其他一些,请尝试将更新行更改为
UPDATE ONLY [Server].[Database].[dbo].[Item]