Dot-Net

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

  • October 9, 2014

這是對這個執行緒的一種跟進。這就是**.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)

無論如何,我覺得這真的很奇怪,所以我嘗試了幾種相同的口味:

  • 為 ODBC 切換 OleDB

  • 循環遍歷數據表並為每一行執行一個 INSERT 語句

    • 這就是 .Update 的作用
  • 使用 ACE 提供程序而不是 Jet(ODBC 和 OleDB)

  • 從 DataReader.Read 循環中執行數據適配器更新

    • 出於沮喪;這很有趣。

最後,我嘗試使用 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

其他一些注意事項:

  • 在所有範例中,所有內容都轉換為字元串,以盡量保持簡單和一致

    • 例外:在我的第一個範例中,使用 Table.Load 函式,我不這樣做是因為……好吧,我真的不能,但是當我遍歷閱讀器並建構插入命令時,我做了基本相同的事情(即無論如何,它在做什麼)。它沒有幫助。
  • 對於每個欄位… Next vs. Field(i) vs. Field(name) 對我來說沒有區別

  • 我執行的每個測試都從一個新壓縮的 Access 數據庫中的空的預建構數據表開始

  • 將數據讀取器載入到記憶體中的數據表大約需要 3 秒

  • 我認為封送數據不是問題,因為 Marc 的文章表明通過自動化載入文本文件與 DAO 一樣快——如果有的話,它不應該在使用 ODBC/OleDB 時封送數據,但應該使用自動化時

  • 所有這一切都讓我感到不安,因為它沒有意義

希望有人能夠對此有所了解……這很奇怪。提前致謝!

這裡的原因是 DAO 驅動程序比 ODBC 驅動程序更接近 MS Access 數據庫引擎。

DAO 方法AddNewUpdate直接委託給 MS Access 等效項,它在任何時候都不會生成 SQL,因此 MS Access 沒有要解析的 SQL。

另一方面,DataAdapter 程式碼為每一行生成一個更新語句,該更新語句被傳遞給 ODBC,然後由它傳遞給 MSAccess 驅動程序,該驅動程序要麼

  1. AddNew獨立地將 SQL 和問題和Update 命令解析到 Access 數據庫或
  2. 將 SQL 傳遞給 MS Access,它沒有針對解析 SQL 進行優化,一旦解析,最終會將 SQL 轉換為AddNew命令 Update

無論哪種方式,您都需要花費時間生成 SQL,然後讓一些東西解釋該 SQL,其中 DAO 方法繞過 SQL 生成/解釋並直接進入金屬。

解決此問題的一種方法是創建您自己的“數據庫服務”,該服務在具有訪問數據庫的機器上執行。這會編組您的選擇和更新,並可以通過遠端處理、WCF(http 或其他)與客戶端進行通信。這是很多工作,並且會極大地改變您的應用程序邏輯。

找出數據庫驅動程序的正確名稱(例如 Jet 或其他)是留給讀者的練習

引用自:https://stackoverflow.com/questions/15788441