2013-04-03 9 views
6

Jest to swego rodzaju kontynuacja do this thread. Wszystko to z . Net 2.0; przynajmniej dla mnie.Aktualizacja danych wsadowych MS Access za pomocą funkcji ADO.Net i COM Interoperability

Zasadniczo Marc (OP z góry) Próbowałem kilka różnych podejść do zaktualizowania tabeli MS Access z 100,000 rekordy i stwierdził, że przy użyciu połączenia DAO była grubsza 10 - 30x szybciej niż przy użyciu ADO.NET. Zszedłem praktycznie tą samą ścieżką (przykłady poniżej) i doszedłem do tego samego wniosku.

Chyba jestem po prostu staramy się zrozumieć dlaczego OleDB i ODBC są o wiele wolniej i chciałabym usłyszeć, jeśli ktoś znalazł lepszą odpowiedź niż DAO od tego stanowiska w 2011 roku będę naprawdę wolą unikać DAO i/lub automatyzacji, ponieważ będą wymagać, aby komputer klienta miał dostęp do redystrybucji lub silnika bazy danych (lub utknąłem z DAO 3.6, który nie obsługuje .ACCDB).

Oryginalna próba; ~ 100 sekund dla 100,000 pozycji/10 kolumn:

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) 

Zresztą myślałem, że to było naprawdę dziwne więc próbowałem kilka odmian tej samej rzeczy:

  • Przełączanie się OleDB ODBC
  • Looping poprzez tabeli danych i prowadzenie INSERT dla każdego wiersza
    • to jest to, co robi i tak .Update
  • Korzystanie dostawcy ACE zamiast Jet (ODBC i OLEDB)
  • Running aktualizację danych z adaptera w pętli DataReader.Read
    • z frustracji; to było zabawne.

Wreszcie, próbowałem używać DAO. Kod powinien zasadniczo robić to samo; z wyjątkiem tego, że wyraźnie nie jest, ponieważ działa to w ~ 10 sekund.

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 

Kilka innych uwagi:

  • Wszystko jest przekształcane na łańcuchy we wszystkich przykładach, aby utrzymać rzeczy tak proste i jak najbardziej spójną
    • Wyjątek: W pierwszym przykładzie, stosując funkcji Table.Load, nie robię tego, ponieważ ... cóż, naprawdę nie mogę, ale w zasadzie to samo zrobiłem, kiedy przełączyłem się przez czytnik i zbudowałem polecenia wstawiania (i tak to się dzieje). To nie pomogło.
  • Dla każdego pola ... Dalej kontra Pole (i) vs.Pole (nazwa) nie miało znaczenia dla mnie
  • Każda próba Pobiegłem rozpoczął z pustego, gotowych tabeli danych w świeżo ubitego bazy danych Access
  • załadowaniu Reader danych do tabeli danych w pamięci trwa ~ 3 sekundy
  • Nie sądzę, że to problem z gromadzeniem danych, ponieważ post Marca wskazywał, że ładowanie pliku tekstowego za pośrednictwem Automatyzacji jest tak szybkie jak DAO - jeśli w ogóle, to nie powinno marnować danych podczas korzystania z ODBC/OleDB, ale to powinno być przy użyciu Automatyzacji
  • Wszystko to przeszkadza mi o wiele bardziej niż powinno, ponieważ nie ma sensu

Mam nadzieję, że ktoś będzie mógł rzucić trochę światła na to ... to po prostu dziwne. Z góry dziękuję!

Odpowiedz

4

Powód jest taki, że sterownik DAO znajduje się znacznie bliżej silnika MS Access Database niż sterownik ODBC.

Metody DAO AddNew i Update delegują bezpośrednio do ekwiwalentów MS Access, w żadnym punkcie nie generują kodu SQL, więc nie ma kodu SQL, który mógłby zostać przetworzony przez MS Access.

Z drugiej strony, kod DataAdapter generuje UPDATE dla każdego wiersza, że ​​oświadczenie zmiana zostanie przekazana do ODBC, który następnie przekazuje go kierowca MSACCESS, które albo

  1. niezależnie analizuje SQL i kwestie AddNew i Update polecenia do bazy danych programu Access lub
  2. przechodzi SQL do MS Access, który nie jest zoptymalizowany do analizowania SQL, i który raz analizowany, kończy się tłumaczenia SQL do AddNew i Update poleceń.

Tak czy inaczej, twój czas jest zajęty, generując SQL, a następnie posiadając coś, co interpretuje ten SQL, gdzie podejście DAO omija generowanie/interpretację kodu SQL i idzie prosto do metalu.

Jednym ze sposobów obejścia tego problemu jest utworzenie własnej "usługi bazy danych" uruchomionej na komputerze z bazą dostępu. Ten marszałek wybiera aktualizacje & i może komunikować się z klientem za pośrednictwem zdalnego połączenia, WCF (http lub cokolwiek innego). To dużo pracy i znacząco zmienia logikę aplikacji.

Zastanawianie się prawidłową nazwę sterownika bazy danych (np Jet lub cokolwiek) to ćwiczenie pozostawiamy czytelnikowi

+0

Dzięki za wyjaśnienie! Wiem, że DAO siedzi prosto na silniku DB, po prostu nigdy nie widziałem * tego * drastycznego uderzenia wydajności po prostu przy użyciu jednej dodatkowej warstwy oprogramowania pośredniego. Czy w takim przypadku główne działanie programu Access jest inne w porównaniu z innymi systemami DBMS, że aktualizacja zwykle uruchamia aktualizację w partiach, zamiast przechodzić przez ODBC dla każdego rekordu? – Karter

+0

Hitem jest ** SO BAD **, ponieważ jest to Access. Nie będzie aż tak źle (tutaj przynęta z płomieniem) a real_ RDBMS, także dla SQL Server (i SQL Server express), możesz użyć klasy 'SqlBulkCopy', która wstawia wiersze z szybkością topienia bliską twarzy. Jeśli możesz, szczerze polecam porzucić MS Access i uruchomić z SQL Express. Używałem programu Access w znacznym stopniu w ciągu dnia i nigdy go nie lubiłem. _ "Ojej, cieszę się, że skorzystałem z dostępu do tego projektu", nie powiedziałam nigdy. –

+1

Nie zgadzam się; ale wiesz, ** dziedzictwo wspiera wszystkie rzeczy ** – Karter

2

wiem, to pytanie jest stary, ale odpowiedź może pomóc ktoś wciąż walczy z tym.

Istnieje inna metoda do rozważenia. Ponieważ oba łańcuchy połączenia źródłowego i docelowego są znane, tabele źródłowe mogą być połączone z docelową bazą danych Access, prawdopodobnie z koniecznym parsowaniem łańcucha połączenia, przez DAO lub ADOX (wiem, że ADOX jest tutaj nietypowy).
Dane w tabelach tak połączone mogą być następnie przeniesione dość szybko wydając oświadczenia, jak to na DAO lub OLEDB połączenia do docelowej bazy danych Access:

SELECT * INTO Table1 FROM _LINKED_Table1 

pewne wady (proszę wskazać niczego Tęskniłem):

  • tabela źródłowa musi zawierać klucz podstawowy
  • klucze podstawowe i indeksy mają być ponownie utworzony przez sprawdzenie schematu indeksy źródłowe
  • niełatwo się postęp transferu s tatus natomiast zapytanie jest uruchomiony

pewne zalety (proszę zwrócić uwagę na coś Tęskniłem):

  • tylko mającą zbadać schematu źródłowe tabele, jeśli wszystkie tabele użytkowników mają być kopiowane
  • nie
  • konieczności sprawdzenia źródłowego schematu Kolumny w celu wygenerowania definicji kolumn dla instrukcji CREATE TABLE
    (na przykład, spróbuj uzyskać wiarygodne informacje AUTONUMBER/IDENTITY ze schematu OleDb, tj. bez założeń dotyczących kombinacji wartości kolumn i bitów flag w oparciu o analizę innych schematów)
  • nie trzeba generować dużych ilości instrukcji INSERT INTO ... VALUES ..., uwzględniając kolumny AUTONUMBER/IDENTITY w kodzie lub w inny sposób uruchomić operację bazy danych dla każdego wiersza w kodzie
  • być w stanie określić kryteria filtrowania przesyłanych rekordy
  • nie martwiąc się o tekst, daty lub kolumn czasu ani sposobu wyznaczania, ucieczki lub sformatowanie ich wartości w zapytaniach z wyjątkiem gdy używany w kryteriach zapytania

metoda ta była stosowana w produkcji projekt i okazał się najszybszy, przynajmniej dla mnie. : o)

Powiązane problemy