簡體   English   中英

如何在SQL Server 2008中加快更新查詢?

[英]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_typorders表1和sorder_nbrorders表和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更新

使用CTE和NEWID()更新表

使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM