【问题标题】:Fastest way to import text file into database将文本文件导入数据库的最快方法
【发布时间】:2010-11-01 18:58:07
【问题描述】:

我有一个文本文件,其中包含自定义格式的数据库表转储记录,该文本在特定位置有一个字符,用于标识该记录的操作:

  • M = 插入或更新
  • D = 删除记录

因此,如果我在文本文件中找到 D 记录,我需要将记录删除到数据库中,相反,如果我找到 M 记录,如果数据库中不存在,我需要插入记录,如果已经存在,我需要更新它。

使用 .NET Framework 和 c# 在数据库表中导入类似文本文件的更好、最快的方法是什么? 我在这个文本文件中有 300000 条平均记录。

谢谢

【问题讨论】:

  • 数据库中有多少条记录需要匹配?
  • 您是在使用 ORM 还是在编写裸 SQL 语句?
  • 您能否说明您所说的最快是什么意思?即,最快的编码方式,最快的运行时间等。
  • 在数据库表中,我平均有 500000 条记录。我可以有 4 种不同类型的数据库服务器:MSSQL、MySQL、PostgreSQL、Firebird 与 ODBC 连接。我会编写一个导入此文本文件的性能良好的代码。
  • 您的文件会包含重复记录吗?例如,是否有可能会有一个“D”记录,然后是一个“M”记录,然后是另一个“D”记录,它们都对应于数据库中的同一条记录?顺序重要吗?

标签: c# database import


【解决方案1】:

最简单的方法可能是使用 ADO.NET 创建一个类型化的数据表来加载数据并相应地设置数据行状态,然后通过 DataAdapter 刷新数据。

最快的方法可能是创建一个批量 SQL 脚本来执行。 LinQ 可以在选择数据时为您节省大量时间(您可能可以即时对其进行转换)。

还应考虑一些特定于平台的解决方案。请参阅此处的 SQLServer 大容量插入。

http://dotnetslackers.com/Community/blogs/xun/archive/2008/04/15/sql-bulk-insert-and-ado-net-sqlbulkcopy.aspx

【讨论】:

    【解决方案2】:

    为什么不解析文本并生成插入、更新和删除语句,然后只运行您生成的脚本?

    【讨论】:

    • 我还会在特定时间间隔添加一些提交以加快速度。
    • 我如何确定 SQL 语句是插入还是更新?我是否需要查询目标表以了解记录是否已存在?
    • @aleroot - 再次阅读您的问题。我没有意识到您使用 M 进行插入和更新。由于记录可能都不同,也许可以在 SQL 脚本中尝试捕获。如果捕获到异常并且错误是记录已存在,请在捕获中进行更新。虽然不是超级优雅。如果你可以做一个 IF EXISTS 让记录独一无二的东西会更好,但我有一种感觉你不会知道每条记录的主键是什么。
    【解决方案3】:

    没有简单的方法可以做到这一点,无论如何,您都必须解析文本以确定您需要运行什么 SQL 语句。您必须自己决定是更新还是插入语句,希望您可以批量处理,否则每次点击“M”时经常访问数据库不是一个好主意。

    【讨论】:

      【解决方案4】:

      如果您使用的是 SQL Server,则可以利用 Bulk Insert functionality。这应该是将文件中的数据插入数据库的最快方法。我要做的第一件事是将文件中的数据插入“登陆表”(即结构与文件结构匹配的表)。另请注意:.NET 2.0 introduced SqlBulkCopy,如果您已经在内存中拥有数据或正在使用某种 DataReader 读取数据,这将同样有用。

      将文件内容插入登录表后,您可以执行一系列 SQL 语句将登录表合并到目标表中。下面是这些 SQL 语句的示例实现(免责声明:我没有检查这些语句的正确性):

      DELETE FROM MyTable
      WHERE EXISTS (
          SELECT 1
          FROM LandingTable
          WHERE
              LandingTable.RecordType = 'D'
              AND LandingTable.KeyField1 = MyTable.KeyField1
              AND LandingTable.KeyField2 = MyTable.KeyField2
      
      
      UPDATE MyTable SET
          MyTable.Field1 = LandingTable.Field1,
          MyTable.Field2 = LandingTable.Field2,
          -- ...
      FROM MyTable
      INNER JOIN LandingTable ON
          LandingTable.KeyField1 = MyTable.KeyField1
          AND LandingTable.KeyField2 = MyTable.KeyField2
      where
          LandingTable.RecordType = 'U'
      
      INSERT INTO MyTable (
          Field1,
          Field2,
          -- ...
      )
      SELECT
          LandingTable.Field1,
          LandingTable.Field2,
          -- ...
      FROM LandingTable
      WHERE
          LandingTable.RecordType = 'I'
      
      -- Consider how to handle "Insert" records where there is already a record in MyTable with the same key
      -- Possible solution below: treat as an "Update"
      UPDATE MyTable SET
          MyTable.Field1 = LandingTable.Field1,
          MyTable.Field2 = LandingTable.Field2,
          -- ...
      FROM MyTable
      INNER JOIN LandingTable ON
          LandingTable.KeyField1 = MyTable.KeyField1
          AND LandingTable.KeyField2 = MyTable.KeyField2
      where
          LandingTable.RecordType = 'I'
      
      -- Now only insert records from LandingTable where there is no corresponding record in MyTable with the same key (determined with a left outer join)
      INSERT INTO MyTable (
          Field1,
          Field2,
          -- ...
      )
      SELECT
          LandingTable.Field1,
          LandingTable.Field2,
          -- ...
      FROM LandingTable
      LEFT OUTER JOIN MyTable ON
          MyTable.KeyField1 = LandingTable.KeyField1
          AND MyTable.KeyField2 = LandingTable.KeyField2
      WHERE
          LandingTable.RecordType = 'I'
          and MyTable.KeyField1 is null
      

      快速搜索后找到的链接:

      【讨论】:

      • 糟糕!我注意到原始问题提到使用“M”来表示插入和更新,而我的代码示例假设“I”表示插入,“U”表示更新。修改示例以使用“M”应该很简单。
      【解决方案5】:

      插入临时表,然后加入更新或删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 2010-11-06
        • 2017-02-06
        相关资源
        最近更新 更多