通过ADO.Net和COM互操作性进行MS Access批量更新

Kar*_*ter 7 .net performance ado.net ms-access dao

这是这个帖子的后续行动.这都是.Net 2.0 ; 对我来说,至少.

从本质上讲,Marc(上面的OP)尝试了几种不同的方法来更新具有100,000条记录的MS Access表,并发现使用DAO连接比使用ADO.Net 大约10-30倍.我走了几乎相同的路径(下面的例子)并得出了相同的结论.

我想我只是想了解为什么 OleDB和ODBC速度要慢得多,我很想听听自2011年那篇文章以来是否有人找到了比DAO更好的答案.我真的更愿意避免使用DAO和/或自动化,因为他们要求客户端机器具有Access或数据库引擎可再发行(或者我坚持使用不支持.ACCDB的DAO 3.6).

原始尝试; 100,000条记录/ 10列约100秒:

Dim accessDB As New OleDb.OleDbConnection( _ 
                      "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
                                accessPath & ";Persist Security Info=True;")
accessDB.Open()

Dim accessCommand As OleDb.OleDbCommand = accessDB.CreateCommand
Dim accessDataAdapter As New OleDb.OleDbDataAdapter( _
                                   "SELECT * FROM " & tableName, accessDB)
Dim accessCommandBuilder As New OleDb.OleDbCommandBuilder(accessDataAdapter)

Dim accessDataTable As New DataTable
accessDataTable.Load(_Reader, System.Data.LoadOption.Upsert)

//This command is what takes 99% of the runtime; loops through each row and runs 
//the update command that is built by the command builder. The problem seems to 
//be that you can't change the UpdateBatchSize property with MS Access
accessDataAdapter.Update(accessDataTable)
Run Code Online (Sandbox Code Playgroud)

无论如何,我觉得这很奇怪所以我尝试了几种同样的东西:

  • 切换OleDB for ODBC
  • 循环遍历数据表并为每一行运行INSERT语句
    • 无论如何,这就是.Update所做的
  • 使用ACE提供程序而不是Jet(ODBC和OleDB)
  • 从DataReader.Read循环中运行Data Adapter Update
    • 出于沮丧; 这很有趣.

最后,我尝试使用DAO.代码应该基本上做同样的事情; 除非它显然不是,因为它在~10秒内运行.

 Dim dbEngine As New DAO.DBEngine
 Dim accessDB As DAO.Database = dbEngine.OpenDatabase(accessPath)
 Dim accessTable As DAO.Recordset = accessDB.OpenRecordset(tableName)

While _Reader.Read
    accessTable.AddNew()
      For i = 0 To _Reader.FieldCount - 1
        accessTable.Fields(i).Value = _Reader.Item(i).ToString
      Next
    accessTable.Update()
End While
Run Code Online (Sandbox Code Playgroud)

其他几点说明:

  • 在所有示例中,所有内容都转换为字符串,以尽可能保持简单和一致
    • 例外:在我的第一个例子中,使用Table.Load函数,我不是因为......好吧,我真的不能,但是当我通过阅读器循环并构建插入命令时,我做了基本相同的事情(这是无论如何,它在做什么.它没有帮助.
  • 对于每个领域......下一个对阵场(i)对阵场(名称)对我没有任何影响
  • 我运行的每个测试都是在一个新压缩的Access数据库中使用一个空的预构建数据表开始的
  • 将数据读取器加载到内存中的数据表大约需要3秒钟
  • 我不认为这是编组数据的问题,因为Marc的帖子表明通过自动化加载文本文件与DAO一样快 - 如果有的话,它不应该在使用ODBC/OleDB时编组数据,但它应该使用自动化时
  • 所有这些都让我感到困扰,因为它没有意义

希望有人能够对此有所了解......这很奇怪.提前致谢!

Bin*_*ier 6

这里的原因是 DAO 驱动程序比 ODBC 驱动程序更接近 MS Access 数据库引擎。

DAO 方法AddNewUpdate直接委托给 MS Access 等效项,它在任何时候都不会生成 SQL,因此 MS Access 没有要解析的 SQL。

另一方面,DataAdapter 代码为每一行生成一个更新语句,该更新语句被传递给 ODBC,然后将其传递给 MSAccess 驱动程序,后者要么

  1. 独立解析 SQL 和问题AddNewUpdate 命令到 Access 数据库或
  2. 传递SQL到MS Access,这是不解析SQL优化,并且其一旦被解析,结束平移SQL入AddNewUpdate命令。

无论哪种方式,您都需要花费时间生成 SQL,然后让某些东西解释该 SQL,其中 DAO 方法绕过 SQL 生成/解释并直接进入金属。

解决此问题的一种方法是创建您自己的“数据库服务”,该服务在具有访问权限的机器上运行。这会编组您的选择和更新,并且可以通过远程处理、WCF(http 或其他方式)与客户端进行通信。这是很多工作,并且会显着改变您的应用程序逻辑。

找出数据库驱动程序的正确名称(例如 Jet 或其他)是留给读者的练习