2009-08-28 78 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