2009-08-28 101 views
1

我在同一個數據庫服務器上有兩個名爲DB1和DB2的數據庫。我有DB2中的Table1和DB2中的Table2。目前,我正在使用插入select *來將表2中的所有數據轉移到表1中(表1爲空,我的目的是將表2中的數據複製到表1)。表結構是聚類ID列(GUID類型)和XML二進制(varbinary)數據列。SQL Server選擇並插入問題

我目前的問題是,內存消耗非常高。有沒有什麼好的想法來減少內存消耗?我的主要想法是我可以初始化幾個小事務並選擇從每個事務插入部分數據。

我正在使用VSTS 2008 + C#+ ADO.Net + SQL Server 2008 Enterprise。任何好的解決方案或參考樣本?

這是我當前的代碼,它會導致內存異常。我正在使用ADO.Net SQLBulkCopy功能。

namespace BulkCopyTable 
{ 
    public class CopyData 
    { 
     string _sourceConnectionString; 
     string _destinationConnectionString; 

     public CopyData(string sourceConnectionString, 
         string destinationConnectionString) 
     { 
      _sourceConnectionString = 
         sourceConnectionString; 
      _destinationConnectionString = 
         destinationConnectionString; 
     } 

     public void CopyTable(string table) 
     { 
      using (SqlConnection source = 
        new SqlConnection(_sourceConnectionString)) 
      { 
       string sql = string.Format("SELECT * FROM [{0}]", table); 

       SqlCommand command = new SqlCommand(sql, source); 

       source.Open(); 
       IDataReader dr = command.ExecuteReader(); 

       using (SqlBulkCopy copy = 
         new SqlBulkCopy(_destinationConnectionString)) 
       { 
        copy.DestinationTableName = table; 
        copy.WriteToServer(dr); 
       } 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      CopyData copier = new CopyData(ConfigurationSettings.AppSettings["source"], ConfigurationSettings.AppSettings["destination"]); 
      Console.WriteLine("Begin Copy"); 
      copier.CopyTable(ConfigurationSettings.AppSettings["Table"]); 
      Console.WriteLine("End Copy"); 
      return; 
     } 
    } 
} 

回答

1

我想你要設置批量大小,這樣你就可以將它們分成可管理的部分。

Bulk copy batch size

檢查是否有其他技術這個批量裝載數據白皮書: Bulk load

+0

謝謝JasonHorner,1.我想確認批量批量的大小。假設我有1M記錄,並且將批量大小設置爲500K,那麼插入第一個500K批次後,SQL Server將從頭開始繼續插入後面的500K批次,而不是重新啓動,對嗎? 2.批量加載文件非常棒!但它是針對SQL Server 2000的,任何相關文檔都適用於更新的SQL Server版本? – George2 2009-08-28 03:09:35

+1

是的,它提交每批作爲一個單獨的交易。 試試這個 http://blogs.msdn.com/sqlcat/archive/2009/02/12/the-data-loading-performance-guide-now-available-from-msdn.aspx 我認爲對於大部分舊材料仍然有用。 – JasonHorner 2009-08-28 03:18:53

+0

謝謝!真的很酷的文件。我會做更多的測試並在這裏給你反饋。 :-) – George2 2009-08-28 03:38:55

2

您可以嘗試使用BCP實用程序。

如果需要,可以使用Process類在C#中運行。

+0

感謝skalburgi,我目前使用SQL批量複製,我想這應該是一樣的BCP? http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx 我一次大量複製將所有數據從源表複製到目標,這將導致出內存錯誤。任何想法將流程拆分爲幾個子流程?我認爲拆分成幾個子流程可能有助於減少內存消耗? – George2 2009-08-28 02:40:04

+1

如何將它分解爲從Table1中選擇一個GUID範圍的運行? (假設你有一個隨機分佈) 例如: 開始:00000000-0000-0000-0000-0000000000 結束:AAAAAAAA-AAAAAAAA-AAAA-AAAAAAAAAA – skalb 2009-08-28 02:48:56

+0

喜skalburgi,1我的GUID是隨機的,任何好想法分裂? :-( 2。我使用BCP從csv文件批量插入到表中,可以使用批量插入從表插入另一個表? – George2 2009-08-28 03:00:58

2

這是一次性工作嗎?如果是這樣,你可以使用DTS或SSIS。
如果沒有,看看你是否可以在框架使用SQLBulkCopy &相關類

編輯:我看到你的代碼&可以使用BatchSize屬性調用在WriteToServer之前建議。

+0

我試圖使用這個類,但仍然耗盡內存。任何想法在SQL批量複製中分割工作? – George2 2009-08-28 02:36:51

+1

請發佈代碼,並且在內存不足的地方和時間添加。 – shahkalpesh 2009-08-28 02:48:16

+0

我已將我的代碼發佈到我的原始答覆中。任何想法如何解決這個問題,使其使用更少的內存? – George2 2009-08-28 03:03:54

1

會設置一個遊標,遍歷源表中的每一行,併爲每個獲取的行「插入選擇」,使用更少的內存? BOL有很多通過遊標步進的例子。


更新:這是我複製從獲取BOL T-SQL參考修正的例子/:(評論來自BOL文章,我只是在幾個人的名字更改)

-- // Declare the variables to store the values returned by FETCH. 
DECLARE @id uniqueidentifier, @xml varbinary(4000) 

DECLARE myCursor CURSOR FOR 
SELECT id, xml FROM Table1 

OPEN myCursor 

-- // Perform the first fetch and store the values in variables. 
-- // Note: The variables are in the same order as the columns 
-- // in the SELECT statement. 

FETCH NEXT FROM myCursor 
INTO @id, @xml 

-- // Check @@FETCH_STATUS to see if there are any more rows to fetch. 
WHILE @@FETCH_STATUS = 0 
    BEGIN 

    -- // Do something with your values! 
    INSERT INTO db2..Table2 (id, xml) SELECT @id, @xml 

    -- // This is executed as long as the previous fetch succeeds. 
    FETCH NEXT FROM myCursor 
    INTO @id, @xml 

    END 

CLOSE myCursor 
DEALLOCATE myCursor 
+0

我喜歡你設置遊標的想法,任何參考樣本? – George2 2009-08-28 03:01:54

+1

我已更新我的回答 – Funka 2009-08-28 04:36:45

+1

這會佔用較少的內存,但需要相當長的時間。 – HLGEM 2009-08-28 13:32:02