簡體   English   中英

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

[英]MS Access Batch Update via ADO.Net and COM Interoperability

這是這個帖子的后續行動。 這都是.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)

無論如何,我覺得這很奇怪所以我嘗試了幾種同樣的東西:

  • 切換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

其他幾點說明:

  • 在所有示例中,所有內容都轉換為字符串,以盡可能保持簡單和一致
    • 例外:在我的第一個例子中,使用Table.Load函數,我不是因為......好吧,我真的不能,但是當我通過閱讀器循環並構建插入命令時,我做的基本相同(這是無論如何,它在做什么。 它沒有幫助。
  • 對於每個領域......下一個對陣場(i)對陣場(名稱)對我沒有任何影響
  • 我運行的每個測試都是在新壓縮的Access數據庫中使用空的預構建數據表開始的
  • 將數據讀取器加載到內存中的數據表大約需要3秒鍾
  • 我不認為這是編組數據的問題,因為Marc的帖子表明通過自動化加載文本文件與DAO一樣快 - 如果有的話,它不應該在使用ODBC / OleDB時編組數據,但它應該使用自動化時
  • 所有這些都讓我感到困擾,因為它沒有意義

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

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

DAO方法AddNewUpdate委托直接到MS Access等價物,它決不會生成SQL,因此MS Access無法解析SQL。

另一方面,DataAdapter代碼為每一行生成一個Update語句,該更新語句將傳遞給ODBC,然后ODBC將其傳遞給MSAccess驅動程序,該驅動程序要么

  1. 獨立解析SQL並向Access數據庫發出AddNewUpdate命令
  2. 將SQL傳遞給MS Access,MS Access未針對解析SQL進行優化,一旦解析,最終將SQL轉換為AddNewUpdate命令。

無論哪種方式,你的時間都會產生SQL,然后有一些東西解釋SQL,DAO方法繞過SQL生成/解釋並直接進入金屬。

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

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

我知道這個問題已經過時了,但答案可能會幫助那些仍在努力解決這個問題的人。

還有另一種方法需要考慮。 由於源連接字符串和目標連接字符串都是已知的,源表可以鏈接到目標Access數據庫,可能需要通過DAO或ADOX進行一些連接字符串解析(我知道,ADOX在這里是偏離主題的)。
通過在DAO或OleDb連接上向目標Access數據庫發出這樣的語句,可以相當快速地傳輸如此鏈接的表中的數據:

SELECT * INTO Table1 FROM _LINKED_Table1

一些缺點(請指出我錯過的任何東西):

  • 源表必須包含主鍵
  • 必須通過檢查源索引架構來重新創建主鍵和索引
  • 在查詢運行時不容易獲得傳輸進度狀態

一些優點(請指出我錯過的任何東西):

  • 如果要復制所有用戶表,則只需要檢查源表模式
  • 不必檢查源Columns模式以生成CREATE TABLE語句的列定義
    (例如,嘗試從OleDb模式中可靠地獲取AUTONUMBER / IDENTITY信息,即不基於檢查其他模式而對列值和標志位的組合進行假設)
  • 不必生成大量的INSERT INTO ... VALUES ...語句,在代碼中考慮AUTONUMBER / IDENTITY列,或者為代碼中的每一行運行數據庫操作
  • 能夠指定過濾轉移記錄的標准
  • 不必擔心文本,日期或時間列或如何在查詢中分隔,轉義或格式化它們的值,除非在查詢條件中使用

這種方法用於生產項目,至少對我來說是最快的。 :O)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM