2012-10-02 39 views
0

更新相對較大的表(〜7000萬行)的推薦方式是什麼,以便用ID爲的不同表替換外鍵列(間接鏈接當前鍵)?修改表中的每一行的最快方法

比方說,我有三個表:

Person 
    Id long, 
    Group_id long --> foreign key to Group table 

Group 
    Id long 
    Device_id long --> foreign key to Device table 

Device 
    Id long 

我想更新Person表有直接的外鍵Device表,即:

Person 
    Id long, 
    Device_Id long --> foreign key to Device table 

Device 
    Id long 

查詢看起來像這樣:

-- replace Group_id with Device_id 
update p from Person p 
    inner join Group g 
    on g.Id = p.Group_id 
set p.Group_id = g.Device_id 

我會冷杉放棄FK約束,然後重命名列。

  • 這項工作?
  • 有沒有更好的方法?
  • 我可以加快速度嗎? (當這個查詢正在運行時,其他所有內容都將處於脫機狀態,服務器爲UPS備份,因此我想跳過任何事務更新)

回答

1

如果您正確編寫UPDATE, SQL Server)的

update p 
set p.Group_id = g.Device_id 
from Person p 
inner join Group g on g.Id = p.Group_id 

除此之外,這是一個非常明智的舉動再利用,然後重命名列*。除非你希望使用WHILE循環和person.Id標記將更新分解爲批處理,否則無法想出任何明智的方法來使其更快。

* -ALTER TABLE DROP COLUMN DOES NOT RECLAIM THE SPACE THE COLUMN TOOK

+0

我在SQL吮吸,LOL。但是「批次」評論實際上最有趣。如果我只是通過SSMS運行它,我相信它會在實際更新表之前創建一個巨大的事務,從而使整個事情變得緩慢並帶來一堆我想避免的磁盤空間。 – Lou

+0

順便說一句,這最後一個鏈接是否適合你?我無法打開它。 – Lou

+0

確實如此,您可以通過谷歌翻譯嘗試:http://translate.google.com/translate?sl=en&tl=fr&js=n&prev=_t&hl=zh-CN&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F% 2Fsqlblogcasts.com%2Fblogs%2Ftonyrogerson%2Farchive%2F2007%2F08%2F27%2Falter表拖放列 - 不 - 不回收-的空間最列了-IT-SA-元數據變化 - only.aspx – RichardTheKiwi

0

你的點子會不會「工作」,除非有每個組只有一個設備(這將是可笑的,所以我想不會)。

問題是,你將不得不將許多device_id值塞進人表中的一列 - 這就是爲什麼你有一個組表。

+0

實際上,一個「組」就像一羣人,而不是一組設備,所以,是的,一個組有一個設備(如問題中所示,請檢查「Device_id」列中的'組'表)。但事實上,所有查詢都需要讓所有人都與單個設備相關,這需要通過「Group」表進行不必要的連接(並且我們希望使「人員」獨立於「組」和任何其他類似的元數據)。 – Lou

+0

Mate,你應該看看DDL中的鏈接。他確實付出了努力,正確地繪製出來。 – RichardTheKiwi

1
  1. 刪除要更新的表上的索引並在更新完成後重新創建。
  2. 在更新完成後,在您正在更新的表上刪除約束並進行適當重新創建(畢竟,您正在更改引用)。
  3. 關閉更新完成後更新並啓用的表上的觸發器。
  4. 您可能想要考慮運行批次。我個人會一次創建一個循環和批量更新10k行。這似乎導致我的硬件上出現最少的問題(磁盤空間不足等)。您可以訂購更新並追蹤PK,以便知道您的位置。或者創建一個特定記錄更新時設置的位列;這個方法可能會讓整體更容易,因爲根本不需要跟蹤PK。

這樣一個循環的一個例子可能是這樣的:

select top 1 * from table 

DECLARE @MinPK BIGINT 
DECLARE @MaxPK BIGINT 
SET @MinPK=0 
SET @MaxPK=0 

WHILE @@ROWCOUNT>0 
BEGIN 
    SELECT 
     @MaxPK=MAX(a.PK) 
    FROM (
     SELECT TOP 3 
      PK 
     FROM Table 
     WHERE PK>@MinPK 
     ORDER BY PK ASC 
    ) a 

    --Change this to an update 
    SELECT 
     PK 
    FROM Table 
    WHERE PK>@MinPK 
    AND PK<[email protected] 

    SET @[email protected] 
END 
+0

+1謝謝!但是,我將如何創建這個循環?假設我沒有一個位列來跟蹤進度,我將如何跟蹤PK?只需使用不同的查詢查看值? – Lou