【问题标题】:Best way to insert 50K records into big table (app. 350 columns) in postgresql在 postgresql 中将 50K 记录插入大表(应用程序。350 列)的最佳方法
【发布时间】:2020-06-06 21:00:47
【问题描述】:

使用 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;
    }
}

关于如何进一步优化的想法?

【问题讨论】:

标签: c# postgresql bulkinsert


【解决方案1】:

将 .csv 文件读入数据库的最快方法是在数据库服务器/DBMS 中进行。

C# 甚至永远无法达到这种性能。充其量您添加负载以通过网络传输整个数据一次。如果您必须从代码中执行此操作,通常有适当的批量插入方式。显然对于 Post Gre 来说,那一个被称为COPY

如果这也不是一个选项,至少做一个明确的数据库事务。在循环中执行插入将使数据库打开并提交一个事务每个插入。相反,使用显式事务处理可以至少在一定程度上提高性能。

【讨论】:

  • 我没有使用显式事务吗?任何代码示例?
  • @alaa_sayegh 第一个选项是根本不使用代码。 |第二个最好的,是使用COPY。 Wiktor 链接了它的文档。 |所以没有更多的代码示例了。
猜你喜欢
  • 1970-01-01
  • 2011-06-03
  • 2016-10-14
  • 2022-08-23
  • 2011-02-15
  • 2023-03-26
  • 2012-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多