使用C#
我正在尝试从csv文件(〜55000条记录)插入具有350列的postgresql table
。我只是从标题和记录(用逗号分隔)中构建insert statement
。像这样:
INSERT INTO public.table(field1,fields2,field3, ..... ,field350) VALUES(?,?,?,?,?,.......,?);
INSERT INTO public.table(field1,fields2,field3, ..... ,field350) VALUES(?,?,?,?,?,.......,?);
INSERT INTO public.table(field1,fields2,field3, ..... ,field350) VALUES(?,?,?,?,?,.......,?);
INSERT INTO public.table(field1,fields2,field3, ..... ,field350) VALUES(?,?,?,?,?,.......,?);
....etc
[我尝试使用batch
,就像收集1000条语句并在transaction
中执行它们一样,但这需要1000条记录,最多需要3秒钟的时间。
[我尝试按照Microsoft
here中的示例进行操作,在该示例中,我在每一行上都调用ExecuteNonQuery()
,但是在1000条记录后我commit
将transaction
调用并开始一个新的transcation
,这占用了每1000条记录约3秒。像这样的东西:
foreach (var line in ReadCsvFileToList(dataFile))
{
try
{
if (firstLine)
{
header = line;
firstLine = false;
continue;
}
else
{
var formattedLine = line.Replace("\"\"", "NULL").Replace("'", "''").Replace("\"", "'");
var commandText = $"INSERT INTO public.table({header.Replace('/', '_')}) VALUES ({formattedLine})";
command.CommandText = commandText;
await command.ExecuteNonQueryAsync();
round++;
}
if (round == 1000) // batch size
{
await transaction.CommitAsync();
Console.WriteLine("batch commited to DB at: " + DateTime.Now.ToString("ddMMyyy hh:mm:ss"));
round = 0;
transaction = connection.BeginTransaction();
}
}
catch (Exception)
{
await connection.CloseAsync();
await connection.DisposeAsync();
await transaction?.RollbackAsync();
throw;
}
}
关于如何进一步优化的想法?
将.csv文件读入数据库的最快方法是在数据库服务器/ DBMS中进行。
C#永远都不会接近这种性能。充其量您可以增加负载以一次通过网络传输整个数据。如果您通过代码执行[[have,通常有一种正确的批量插入方法。显然对于Post Grey来说,这个名字叫做COPY。
如果也不可行,至少要进行显式的DB事务。在循环中执行插入操作将打开数据库并提交事务每一个
INSERT。相反,使用这种方式来进行显式事务处理至少可以改善性能。