2009-07-14 155 views
1
update auditdata set TATCallType='12',TATCallUnit='1' from auditdata auditdata 
     inner join Auditdata_sms_12 a_sns 
     on auditdata.ID = a_sns.id 

當我上面查詢它需要超過10分鐘執行。緩慢更新(主鍵)

什麼錯在這個

Auditdata.ID是主鍵..

如果我運行更新命令也更新索引??? 是這個原因讓更新的速度很慢

+1

哪個DBMS?桌子大概有多大?這是剛剛開始發生在現有的查詢,還是這是一個新的查詢? – 2009-07-14 16:16:30

+0

- 你的主鍵是什麼數據類型? - 你在這張桌子上有什麼索引? – 2009-07-14 16:17:56

+0

桌子有多大?如果這是100,000,000行,並且它必須更新每一行,那麼它對你有什麼索引無關緊要:這將需要一段時間。 – Eric 2009-07-14 16:20:15

回答

1

查看您的評論,主表包含的行少於臨時表。

嘗試使用EXISTS子句(或在某種意義上,比較減少至行(數即150萬)

update auditdata set TATCallType='12',TATCallUnit='1' 
from auditdata auditdata 
WHERE EXISTS 
(SELECT id from Auditdata_sms_12 a_sns WHERE a_sns.id = auditdata.ID) 

這樣做是爲了限制比較

編輯:AuditdataSMS12應該有關於ID索引能夠快速獲得該行。這就是你實際上是在尋找爲某個ID的表。

0

更新 我再次閱讀初始查詢,你不更新主ID字段後實現,但另外2個數據字段。請重新閱讀我的回覆的第一個陳述並相應發表評論。抱歉。

是否有您所更新要麼字段中定義一個聚集索引?聚簇索引有很多好處,我不知道它們,但它們可能在更新期間導致大量的性能命中。我的理解是,聚集索引的更新可能導致整個索引必須重新編譯。如果表中有很多數據,這肯定會導致您的問題。

此外,還要確保有在表上沒有觸發器。如果觸發器行爲不正確,可能會導致相同的性能下降。

0

多久簡單的選擇(例如

select id from auditdata auditdata 
    inner join Auditdata_sms_12 a_sns 
    on auditdata.ID = a_sns.id 

)以及它找到了多少條記錄?

如果SQL Server必須通讀所有500萬點的記錄,或更新一百萬條記錄,並沒有足夠的內存或足夠快的硬件,那麼就可能沒有什麼你與查詢。

你可能需要監視SQL服務器的硬件和更要看查詢計劃,看看有什麼位佔用的時間。

2

這裏有一些東西在玩。

首先,SQL語句看起來破裂。更新中的「FROM」子句旨在用作JOIN'd更新。由於您使用硬編碼值更新行,因此無需這樣做。

其次,更深奧的是,如果索引是正確的,就像你說的那樣,那麼你可能是在處理初始寫入或事務日誌區域的緩慢磁盤I/O(在Oracle中爲撤消,登錄SQL Server等)。

作爲一個健全的檢查,我會做兩件事。一,只更新尚未設置條件的行。許多DBMS產品將愉快地爲不改變的行執行物理磁盤I/O(儘管許多不)。嘗試與極限。

二,以較小的批次應用更新。這對於日誌爭用和較慢的磁盤確實有幫助。

所以,像下面的最初嘗試:

UPDATE auditdata 
    SET TATCallType = '12' 
    , TATCallUnit = '1' 
    FROM auditdata 
WHERE TATCallType <> '12' 
    AND TATCallUnit <> '1' 
    AND EXISTS(SELECT * 
       FROM Auditdata_sms_12 a_sns 
       WHERE a_sns.id = auditdata.ID) 

如果你想要做的批次,在SQL Server中這是很容易:

SET ROWCOUNT 2000 

UPDATE ... 

(run continually in a loop via T-SQL or by hand until @@ROWCOUNT = 0) 

SET ROWCOUNT 0