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(已删除坏行)。或者逐行进行异步导入,但我认为行可能会按顺序被打乱,或者丢失甚至重复。有人能给我小费吗。
一行的大容量插入比单行插入慢10倍以上。你目前的策略不起作用。
验证并清除客户端上的数据。必须保证插入成功。将其复制到DataTable
中。一次插入全部,或者至少插入大批量(性能增益开始出现在100或1000行)。
如前所述,显而易见的解决方案是在从CSV文件读取数据时验证数据,并仅用"好行"填充数据表。
如果您的验证包括数据类型检查,即如果字符串可由目标系统(此处:SQL Server)转换,则您将在此处复制逻辑,即重新编程SQL Server中已实现的解析/转换逻辑。这不是一个大问题,但从设计方面来说并不一定明智。
实际上,您可以使用BULK INSERT
命令将CSV文件直接导入SQL Server。
因此,另一种方法可能是将原始数据导入服务器中的临时表中,然后进行数据类型检查。当您碰巧运行SQL 2005或更高版本时,这非常容易。它们引入了类似ISDATE
和ISNUMERIC
的功能。
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多万行,其中一些行已损坏,或者我们根本不感兴趣。