我必须创建将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(删除坏行)。或者逐行进行一些异步导入,但我认为行可能会在那里排序或者错过甚至重复。有人可以给小费。
答案 0 :(得分:1)
一行的批量插入比单行插入慢> 10倍。您当前的策略不起作用。
验证并清理客户端上的数据。必须保证插入成功。将其复制到DataTable
。一次插入所有,或至少大批量(穿孔增益开始出现在100或1000行)。
答案 1 :(得分:1)
如上所述,显而易见的解决方案是验证从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)
如果出现以下情况,我个人会这样:
E.g。我们以这种方式分析日志文件。它们包含50 Mio +行,其中一些已损坏或我们根本不感兴趣。