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

本文关键字:非常 逐行 WriteToServer DataTable SqlBulkCopy | 更新日期: 2023-09-27 18:27:43

我不得不制作一个将csv文件导入数据库表的应用程序。csv文件类似于~500rows ~30columns,来源不太可靠(可能包含损坏的数据)。

我是这样做的CSV->DataTable->SqlBulkCopy.WriteToServer(DataTable)。它处理500条记录到非本地sql server,大约4秒,这不是一个大问题。但由于csv可能包含损坏的数据(错误的日期格式、整数溢出等),我不得不使其不出错,并导入好的行和跳过坏的行。将损坏的数据处理到DataTable时不会出现问题,但将DataTable导入数据库时不会出现此问题。我所做的是尝试{}在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进行正向和反向通信。我该怎么解决这个问题。我在考虑模拟一些类似于数据库表设计的本地克隆的东西。请逐行尝试{}所有数据表,然后排除坏行,然后在1处导入整个DataTable(已删除坏行)。或者逐行进行异步导入,但我认为行可能会按顺序被打乱,或者丢失甚至重复。有人能给我小费吗。

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

一行的大容量插入比单行插入慢10倍以上。你目前的策略不起作用。

验证并清除客户端上的数据。必须保证插入成功。将其复制到DataTable中。一次插入全部,或者至少插入大批量(性能增益开始出现在100或1000行)。

如前所述,显而易见的解决方案是在从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进行编码

例如,我们以这种方式分析日志文件。它们包含5000多万行,其中一些行已损坏,或者我们根本不感兴趣。