Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Jak zwiększyć wydajność zbiorczych operacji WSTAWIANIA do tabel połączonych ODBC w programie Access?

Ta sytuacja nie jest rzadkością, gdy mamy do czynienia z masowymi wstawkami do tabel połączonych ODBC w programie Access. W przypadku następującego zapytania dostępu

INSERT INTO METER_DATA (MPO_REFERENCE) 
SELECT MPO_REFERENCE FROM tblTempSmartSSP

gdzie [METER_DATA] to połączona tabela ODBC, a [tblTempSmartSSP] to lokalna (natywna) tabela dostępu, ODBC jest nieco ograniczone pod względem tego, jak sprytny może być, ponieważ musi być w stanie obsłużyć szeroką gamę docelowych baz danych, których możliwości mogą się różnić bardzo. Niestety często oznacza to, że pomimo pojedynczej instrukcji Access SQL to, co faktycznie jest wysyłane do zdalnej (połączonej) bazy danych, to osobna INSERT (lub odpowiednik) dla każdego wiersza w lokalnej tabeli . Zrozumiałe, że może to być bardzo powolne, jeśli tabela lokalna zawiera dużą liczbę wierszy.

Opcja 1:natywne wstawianie zbiorcze do zdalnej bazy danych

Wszystkie bazy danych mają co najmniej jeden natywny mechanizm zbiorczego ładowania danych:Microsoft SQL Server ma „bcp” i BULK INSERT , a Oracle ma "SQL*Loader". Mechanizmy te są zoptymalizowane pod kątem operacji masowych i zwykle oferują znaczne korzyści w zakresie szybkości. W rzeczywistości, jeśli dane muszą zostać zaimportowane do programu Access i „masowane” przed przesłaniem do zdalnej bazy danych, nadal może być szybciej zrzucić zmodyfikowane dane z powrotem do pliku tekstowego, a następnie zbiorczo zaimportować je do zdalnej bazy danych.

Opcja 2:używanie zapytania przekazującego w programie Access

Jeśli mechanizmy importu zbiorczego są niewykonalne, inną możliwością jest utworzenie co najmniej jednego zapytania przekazującego w programie Access w celu przesłania danych przy użyciu instrukcji INSERT, które mogą wstawiać jednocześnie więcej niż jeden wiersz.

Na przykład, jeśli zdalną bazą danych był SQL Server (2008 lub nowszy), moglibyśmy uruchomić zapytanie tranzytowe Access (T-SQL) w ten sposób

INSERT INTO METER_DATA (MPO_REFERENCE) VALUES (1), (2), (3)

aby wstawić trzy wiersze z jedną instrukcją INSERT.

Zgodnie z odpowiedzią na inne wcześniejsze pytanie, odpowiednia składnia Oracle byłaby

INSERT ALL
    INTO METER_DATA (MPO_REFERENCE) VALUES (1)
    INTO METER_DATA (MPO_REFERENCE) VALUES (2)
    INTO METER_DATA (MPO_REFERENCE) VALUES (3)
SELECT * FROM DUAL;

Testowałem to podejście z SQL Server (ponieważ nie mam dostępu do bazy danych Oracle) przy użyciu natywnej tabeli [tblTempSmartSSP] z 10 000 wierszy. Kod ...

Sub LinkedTableTest()
    Dim cdb As DAO.Database
    Dim t0 As Single

    t0 = Timer
    Set cdb = CurrentDb
    cdb.Execute _
            "INSERT INTO METER_DATA (MPO_REFERENCE) " & _
            "SELECT MPO_REFERENCE FROM tblTempSmartSSP", _
            dbFailOnError
    Set cdb = Nothing
    Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub

... wykonanie w moim środowisku testowym zajęło około 100 sekund.

Natomiast poniższy kod, który buduje wielowierszowe INSERT, jak opisano powyżej (używając tego, co Microsoft nazywa konstruktorem wartości tabeli) ...

Sub PtqTest()
    Dim cdb As DAO.Database, rst As DAO.Recordset
    Dim t0 As Single, i As Long, valueList As String, separator As String

    t0 = Timer
    Set cdb = CurrentDb
    Set rst = cdb.OpenRecordset("SELECT MPO_REFERENCE FROM tblTempSmartSSP", dbOpenSnapshot)
    i = 0
    valueList = ""
    separator = ""
    Do Until rst.EOF
        i = i + 1
        valueList = valueList & separator & "(" & rst!MPO_REFERENCE & ")"
        If i = 1 Then
            separator = ","
        End If
        If i = 1000 Then
            SendInsert valueList
            i = 0
            valueList = ""
            separator = ""
        End If
        rst.MoveNext
    Loop
    If i > 0 Then
        SendInsert valueList
    End If
    rst.Close
    Set rst = Nothing
    Set cdb = Nothing
    Debug.Print "Elapsed time " & Format(Timer - t0, "0.0") & " seconds."
End Sub

Sub SendInsert(valueList As String)
    Dim cdb As DAO.Database, qdf As DAO.QueryDef

    Set cdb = CurrentDb
    Set qdf = cdb.CreateQueryDef("")
    qdf.Connect = cdb.TableDefs("METER_DATA").Connect
    qdf.ReturnsRecords = False
    qdf.sql = "INSERT INTO METER_DATA (MPO_REFERENCE) VALUES " & valueList
    qdf.Execute dbFailOnError
    Set qdf = Nothing
    Set cdb = Nothing
End Sub

... uzyskanie tych samych wyników zajęło od 1 do 2 sekund.

(Konstruktory wartości tabel T-SQL są ograniczone do wstawiania 1000 wierszy na raz, więc powyższy kod jest nieco bardziej skomplikowany, niż byłby w innym przypadku).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Słowo kluczowe Oracle „Partition By” i „Row_Number”

  2. Liczba piątków między dwiema datami

  3. SYS_GUID() Funkcja w Oracle

  4. Nowe funkcje bazy danych Oracle 20c

  5. Jaka jest podwójna tabela w Oracle?