SqlBulkCopy.WriteToServer(DataTable)逐行:非常慢

时间:2014-10-25 08:11:22

标签: c# sqlbulkcopy

我必须创建将csv文件导入数据库表的应用程序。 csv文件类似于~500rows ~30columns,来自不太可靠的来源(可能包含损坏的数据)。

我这样做CSV->DataTable->SqlBulkCopy.WriteToServer(DataTable)。它处理500条记录到非本地sql服务器大约 4秒,这不是一个大问题。但由于csv可能包含损坏的数据(错误的日期格式,整数溢出等),我必须使其成为错误证明并导入良好的行并跳过坏行。将损坏的数据处理到DataTable但将DataTable导入DataBase时不会发生问题。我做的是TRY {}在DB中逐行添加。

int Row = 0;
//csvFileData is the DataTable filled with csv data

foreach(DataRow RowToAdd in csvFileData.Rows) 
{
    //here it spents 1-2% of the time (problem not in DT  row by row processing)
    Row++;
    DataTable TempDT = new DataTable();
    TempDT = csvFileData.Clone();
    TempDT.ImportRow(RowToAdd);

    try 
    { 
        //here it spents 98% of the time
        s.WriteToServer(TempDT);

    } 
    catch(Exception importex)
    {
        Console.WriteLine("Couldn't import {0} row, reason", Row, importex.Message);
    }

}

主叫: s.WriteToServer(scvFileData);
只有一次在我的情况下并不好。

结束它真的很好。问题是执行时间增加到15秒这是很多。因为它与每行的DB进行前向和后向通信。我怎样才能解决这个问题。我正在考虑模拟像DataBase表设计的本地克隆之类的东西。在其上逐行尝试{},然后排除坏的,然后在其中导入整个DataTable(删除坏行)。或者逐行进行一些异步导入,但我认为行可能会在那里排序或者错过甚至重复。有人可以给小费。

2 个答案:

答案 0 :(得分:1)

一行的批量插入比单行插入慢> 10倍。您当前的策略不起作用。

验证并清理客户端上的数据。必须保证插入成功。将其复制到DataTable。一次插入所有,或至少大批量(穿孔增益开始出现在100或1000行)。

答案 1 :(得分:1)

如上所述,显而易见的解决方案是验证从CSV文件中读取数据并仅使用“良好行”填充数据表。

如果您的验证包括数据类型检查,即如果字符串可由目标系统(此处为:SQL-Server)转换,则可以在此处复制逻辑,即重新编程已在SQL Server中实现的解析/转换逻辑。这不是一个大问题,但从设计方面来说不一定是聪明的。

实际上,您可以使用BULK INSERT命令将CSV文件直接导入SQL-Server。

所以另一种方法可能是将原始数据导入服务器中的临时表,然后进行数据类型检查。当您碰巧运行SQL 2005或更高版本时,这非常容易。他们引入了ISDATEISNUMERIC等函数。

BULK INSERT CSVRawData FROM 'c:\csvtest.txt' WITH (
  FIELDTERMINATOR = ',', ROWTERMINATOR = '\n'
)

INSERT INTO FinalTable 
SELECT * from CSVRawData
 WHERE ISDATE(DateField) 
   and ISNUMERIC (NumericField)

如果出现以下情况,我个人会这样:

  • CSV文件具有固定格式
  • 正在进行的完整性检查很容易在SQL中编码

E.g。我们以这种方式分析日志文件。它们包含50 Mio +行,其中一些已损坏或我们根本不感兴趣。