2009-09-06 48 views
3

我需要編寫一些代碼來插入大約300萬行數據。
同時我需要插入相同數量的伴隨行。什麼是快速插入SQL數據和相關行的最佳方式?

I.e.模式是這樣的:

Item 
    - Id 
    - Title 

Property 
    - Id 
    - FK_Item 
    - Value 

我第一次嘗試是一件隱約這樣的:

BaseDataContext db = new BaseDataContext(); 
foreach (var value in values) 
{ 
    Item i = new Item() { Title = value["title"]}; 
    ItemProperty ip = new ItemProperty() { Item = i, Value = value["value"]}; 
    db.Items.InsertOnSubmit(i); 
    db.ItemProperties.InsertOnSubmit(ip); 
} 
db.SubmitChanges(); 

顯然,這是非常緩慢的,所以我現在用的是這樣的:

BaseDataContext db = new BaseDataContext(); 
DataTable dt = new DataTable("Item"); 
dt.Columns.Add("Title", typeof(string)); 
foreach (var value in values) 
{ 
    DataRow item = dt.NewRow(); 
    item["Title"] = value["title"]; 
    dt.Rows.Add(item); 
} 
using (System.Data.SqlClient.SqlBulkCopy sb = new System.Data.SqlClient.SqlBulkCopy(db.Connection.ConnectionString)) 
{ 
    sb.DestinationTableName = "dbo.Item"; 
    sb.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Title", "Title")); 
    sb.WriteToServer(dt); 
} 

但是這不允許我添加相應的'Property'行。

我在想最好的解決方案可能是添加一個像this one這樣的存儲過程,它通常允許我進行批量插入(或者至少多次插入,但我可能會以某種方式禁止在存儲過程中記錄性能)以及然後返回相應的ID。

任何人都可以想到更好的(即更簡潔,幾乎相同的性能)解決方案嗎?

回答

3

要結合前面的兩個最好的答案,並添加所缺件的標識:

1)使用BCP將數據加載到這樣

CREATE TABLE stage(Title AS VARCHAR(??), value AS {whatever}); 

定義一個臨時的「臨時」表而你所需要的性能以後適當的索引:

CREATE INDEX ix_stage ON stage(Title); 

2)使用SQL INSERT加載項表:

INSERT INTO Item(Title) SELECT Title FROM stage; 

3)通過與項目結合階段最後加載屬性表:

INSERT INTO Property(FK_ItemID, Value) 
SELECT id, Value 
FROM stage 
JOIN Item ON Item.Title = stage.Title 
+0

當然,但是這個假設標題是獨一無二的(它可能是,但我不會依賴它,但這可能是最好的方向 – 2009-09-06 15:12:11

+0

我不得不承擔一些,因爲你沒有提供源表的信息。你必須有一些方法來唯一地關聯信息:依賴於記錄順序在SQL中是無效的 – RBarryYoung 2009-09-06 21:18:40

+0

也就是說,你可以在登臺表上添加一個用於關聯的ID(通常即使在順序依賴關係下也可以),但它可以獲得更復雜 – RBarryYoung 2009-09-06 21:19:54

3

將大量數據移入SQL Server的最佳方式是bcp。假設數據以某種文件形式開始,您需要編寫一個小腳本將數據彙集到兩個表中。或者,您可以使用bcp將數據彙集到一個表中,然後使用SP將數據插入到兩個表中。

+0

問題是,我無法將第二批數據「彙集」到一張表中,而沒有在第一個表中使用相應的ID。我想一個解決方案是分配一個虛假的ID,然後刪除這個,但這似乎不是一個長期做這件事的好方法。 – 2009-09-06 13:32:40

+0

感謝指向我bcp,但看起來很有用。 – 2009-09-06 13:33:16

+0

+1指向BCP – RBarryYoung 2009-09-06 13:59:31

2

將數據批量複製到一個臨時表中,然後調用一個存儲過程,該過程將數據拆分爲需要填充的兩個表。

+0

謝謝,可能是最好的方法。 – 2009-09-06 13:42:02

+0

+1:加入使用BCP,除非你有充分的理由不這樣做(這大約比SQLBulkCopy快大約30%),這就是SOP的答案。 – RBarryYoung 2009-09-06 13:45:36

+0

是的,如果可以,請使用BCP超過批量複製。 – Joe 2009-09-06 15:28:54

2

您可以在代碼中批量複製,以及使用.NET SqlBulkCopy類。

+0

我使用.NET SqlBulkCopy類,你可以指向我應該看的地方? – 2009-09-06 15:10:53

+2

如果您完全控制了數據,也許您可​​以利用SqlBulkCopyOptions的KeepIdentity選項構造函數的參數。這樣,您就可以獲取當前可用的最高身份值,並從那裏開始工作。 – 2009-09-06 15:20:38

+0

謝謝大衛......這只是幫助我。 – John 2009-09-09 21:25:20

相關問題