[英]How to speed up update query in SQL Server 2008?
update orders
set tname = (select top 1 t.task
from task t
where prod_typ='2' and sorder_nbr = t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='2'
update orders
set tname= (select top 1 t.task
from task t
where prod_typ='1' and sorder_nbr=t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='1'
我正在嘗試通過task
表中的最新任務來更新orders
表的tname
列
然后,條件是prod_typ
的orders
表1和sorder_nbr
的orders
表和order_nbr task
表相等
我的第一個更新語句在行為900k的情況下運行良好,第二個更新行在第二個更新語句為400k的情況下運行需要一個多小時,最后我取消了查詢
1)您查詢和我的查詢:
update orders
set tname = (select top 1 t.task
from task t
where prod_type='2' and order_nbr = t.ORDER_NBR
order by t.strt_dt desc)
where Prod_type='2';
go
update o
set tname = (select top 1 t.task
from task t
where prod_type='2' and o.order_nbr = t.ORDER_NBR
order by t.strt_dt desc)
from dbo.orders o
where Prod_type='2';
go
實際執行計划:
如您所見,如果當前數據庫的默認排序規則為CI(不區分大小寫),則遵循謂詞order_nbr=t.ORDER_NBR
強制SQL Server將t.ORDER_NBR
的值與同一表task t
order_nbr
列的值進行比較。 查看與第一個查詢相對應的第一個執行計划。
為了解決剛才這個問題,我用另一個別名dbo.orders o
,我已經reqrite謂詞從而o.order_nbr = t.ORDER_NBR
。 您可能還會在第二個執行計划中看到這一點。
根據每種order_num和prod_type的任務數量,您可以測試S#1(如果有很多任務),或者測試S#2(如果每個order_num和prod_type的任務數量很少)。 同樣,您需要測試數據以查看哪種解決方案更好。
2)解決方案1:
UPDATE o
SET tname =
COALESCE(
(SELECT TOP(1) t.task
FROM dbo.task t
WHERE t.prod_type=o.Prod_type
AND o.order_nbr = t.ORDER_NBR
ORDER BY t.strt_dt DESC), tname
)
FROM dbo.orders o
WHERE o.Prod_type IN ('1', '2');
3)解決方案2:
UPDATE o
SET tname = lt.task
FROM dbo.orders o
INNER JOIN
(
SELECT src.order_nbr, src.prod_type, src.task
FROM (
SELECT t.ORDER_NBR, t.prod_type, t.task,
ROW_NUMBER() OVER(PARTITION BY t.ORDER_NBR, t.prod_type ORDER BY t.strt_dt DESC) RowNum
FROM dbo.task t
) src
WHERE src.RowNum = 1
) lt -- last task
ON o.order_nbr = lt.ORDER_NBR AND o.prod_type = lt.prod_type
WHERE o.Prod_type IN ('1', '2');
如果您有任何疑問,請隨時提問。
4) dbo.task(order_nbr, prod_type, strt_dt) include (task)
)的索引應該對這兩種解決方案都有幫助。
5)您還應該發布實際的執行計划。
嘗試這樣的事情。 這將同時更新prod_type的1和2。
UPDATE orders
SET tname = t1.task
FROM orders o
CROSS APPLY (
SELECT order_nbr, prod_type, t.task, row_number() OVER (PARTITION BY order_nbr, prod_type ORDER BY strt_dt DESC) rownumber
FROM task t
WHERE o.prod_type = t.prod_type
AND o.order_nbr = t.order_nbr) t1
WHERE t1.rownumber = 1
AND o.prod_type in (1,2)
如果數據量大於我建議您使用變量更新表,或使用CTE更新
我希望這個能幫上忙
將tname(t.task)作為(從任務t中選擇前1個t.task,其中prod_typ ='2'並且order_nbr = t.ORDER_NBR按t.strt_dt desc排序)插入Orders(t.task)
使用CTE查詢將加快此過程,因為不需要為每一行都創建子查詢,因此它是預先准備的。 這是sqlfiddle
;with cteTaskNames as
(
select top 1 t.task
from task t
where prod_type='2' and order_nbr=t.ORDER_NBR
order by t.strt_dt desc
)
update orders
set tname = (select task from cteTaskNames)
where Prod_type='2'
go
另外,1)“ prod_type”是整數字段還是字符串字段? 2)如果在cte中添加group by,則可以對訂單和cte查詢執行內部聯接,以一次運行所有更新,而不必執行每個查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.