Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Làm cách nào để tăng hiệu suất cho INSERT hàng loạt vào bảng được liên kết ODBC trong Access?

Tình huống này không phải là hiếm khi xử lý INSERT hàng loạt cho các bảng được liên kết ODBC trong Access. Trong trường hợp truy vấn Access sau

INSERT INTO METER_DATA (MPO_REFERENCE) 
SELECT MPO_REFERENCE FROM tblTempSmartSSP

trong đó [METER_DATA] là bảng được liên kết ODBC và [tblTempSmartSSP] là bảng Access cục bộ (gốc), ODBC hơi hạn chế về mức độ thông minh của nó vì nó phải có khả năng cung cấp nhiều loại cơ sở dữ liệu mục tiêu có khả năng khác nhau rất nhiều. Thật không may, điều đó thường có nghĩa là mặc dù một câu lệnh Access SQL duy nhất, những gì thực sự được gửi đến cơ sở dữ liệu từ xa (được liên kết) là một INSERT riêng biệt (hoặc tương đương) cho mỗi hàng trong bảng cục bộ . Nói một cách dễ hiểu, điều đó có thể diễn ra rất chậm nếu bảng cục bộ chứa một số lượng lớn các hàng.

Tùy chọn 1:Chèn hàng loạt gốc vào cơ sở dữ liệu từ xa

Tất cả các cơ sở dữ liệu đều có một hoặc nhiều cơ chế riêng để tải dữ liệu hàng loạt:Microsoft SQL Server có "bcp" và BULK INSERT và Oracle có "SQL * Loader". Các cơ chế này được tối ưu hóa cho các hoạt động hàng loạt và thường sẽ mang lại lợi thế về tốc độ đáng kể. Trên thực tế, nếu dữ liệu cần được nhập vào Access và được "xoa bóp" trước khi được chuyển đến cơ sở dữ liệu từ xa, thì việc kết xuất dữ liệu đã sửa đổi trở lại tệp văn bản và sau đó nhập hàng loạt vào cơ sở dữ liệu từ xa vẫn có thể nhanh hơn.

Tùy chọn 2:Sử dụng truy vấn chuyển tiếp trong Access

Nếu cơ chế nhập hàng loạt không phải là một tùy chọn khả thi, thì một khả năng khác là tạo một hoặc nhiều truy vấn chuyển qua trong Access để tải lên dữ liệu bằng cách sử dụng câu lệnh INSERT có thể chèn nhiều hàng cùng một lúc.

Ví dụ:nếu cơ sở dữ liệu từ xa là SQL Server (2008 trở lên) thì chúng tôi có thể chạy truy vấn chuyển qua Access (T-SQL) như thế này

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

để chèn ba hàng với một câu lệnh INSERT.

Theo một câu trả lời cho một câu hỏi khác trước đó ở đây, cú pháp tương ứng cho Oracle sẽ là

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;

Tôi đã thử nghiệm phương pháp này với SQL Server (vì tôi không có quyền truy cập vào cơ sở dữ liệu Oracle) bằng cách sử dụng bảng [tblTempSmartSSP] gốc có 10.000 hàng. Mã ...

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

... mất khoảng 100 giây để thực thi trong môi trường thử nghiệm của tôi.

Ngược lại, đoạn mã sau tạo các INSERT nhiều hàng như được mô tả ở trên (sử dụng cái mà Microsoft gọi là Bộ tạo giá trị bảng) ...

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

... mất từ ​​1 đến 2 giây để tạo ra kết quả tương tự.

(Trình tạo giá trị bảng T-SQL được giới hạn trong việc chèn 1000 hàng cùng một lúc, vì vậy đoạn mã trên phức tạp hơn một chút so với cách khác.)



  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ố liệu thống kê động thích ứng giết chết hiệu suất trong 12.1.0.2 RAC

  2. Hàm ADD_MONTHS () trong Oracle

  3. có chức năng nào để dịch dữ liệu trong sql không

  4. Thiết lập môi trường phát triển để học PL / SQL

  5. Oracle - Cách tạo tập lệnh từ nhà phát triển sql