Sql-Server
在 100 毫米記錄上使用 JOIN 更新,如何更好地做到這一點?(在 T-SQL 中)
我需要更新單個表中的 1 億條記錄,實際上,通過用簡單的 ID 替換列的 varchar 值來規範化表。(我說的是“替換”,但實際上我是在將 ID 寫入另一列。)
我想要實現的是規範化數據集。尚未標準化的數據沒有索引。我的想法是,我不會在原始值上建立索引,而是在更新完成后索引將用 tinyint 值替換 varchar 值的外鍵。
UPDATE A SET A.AutoClassID = B.AutoClassID FROM AutoDataImportStaging.dbo.Automobile as A JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)
背景
- 在 Server 2008 R2 上使用 MSSQL 2008 R2
- 伺服器有 8 GB RAM
- 伺服器有一個 RAID10,7200 RPM SATA(不是很好,我知道,在生產中這只會讀取數據而不會寫入數據;加上最近的 HD 短缺,這使得成本變得必要)
- 伺服器具有雙四核 Xeon CPU
- 機器沒有做任何其他事情(目前專用於開發,只有這個過程)
- 打開了簡單的日誌記錄(? - 但它仍然記錄以便它可以回滾嗎?)
- 請注意,查詢引用了兩個不同的數據庫,這是值得的
- 更新表中記錄的“寬度”為 455 字節
執行期間的資源
- 物理 RAM 已用盡
- 磁碟 I/O 已用盡
- CPU 幾乎沒有做任何事情(阻塞點是 I/O)
- 執行時間已經 14 小時,而且還在繼續!
我懷疑一些事情,比如我需要原始數據的索引,即使我將在規範化更新後刪除列 (AutoClassName)。我還想知道我是否應該一次只循環一條記錄而不是 JOIN,這在我開始時似乎很荒謬,但現在似乎會更快。
我應該如何更快地更改我剩餘的標準化更新(類似於這個)的方法?
您正在嘗試將其作為單個(非常大)事務來執行。相反,請以較小的批次進行更新。
- SET ROWCOUNT但請注意,這在 2012 年已棄用。
- 更新頂部
您還將受益於:
- AutoData.dbo.AutoClass.AutoClassName 上的臨時索引
- 更多記憶體。更多的記憶體。
我會採取不同的方法。
無需更新現有表,只需建構一個包含您需要的新表即可。
這幾乎肯定會更快:
SELECT DISTINCT AutoClassID, <Other fields> INTO AutoDataImportStaging.dbo.Automobile FROM AutoData.dbo.AutoClass
正如目前所寫,發生了很多邏輯操作:
- 讀取 A.AutoClassName 的所有值
- 讀取 B.AutoClassName 的所有值
- 比較 A 值和 B 值
- 匹配集合中,讀取 B.AutoClassID 的所有值
- 通過存在的任何索引將 A.AutoClassId 的現有值更新為 B.AutoClassId 值