UPDATE einer Access-Tabelle dauert zu lange

  • VB.NET
  • .NET (FX) 4.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von us4711.

    UPDATE einer Access-Tabelle dauert zu lange

    Hallo zusammen,

    folgender Programmcode funktioniert bei kleinen Datenmengen prima:

    Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. strCONLOC = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\TEST\TEST.MDB;Jet OLEDB:Database Password=TEST;Jet OLEDB:System Database=C:\TEST\TESTSYS.MDW;User ID=TEST;Password=TEST"
    3. Dim conn As New OleDbConnection(strCONLOC)
    4. Dim da As New OleDbDataAdapter("SELECT * FROM tblTEST", conn)
    5. Dim ds As New DataSet()
    6. da.Fill(ds, "tblTEST")
    7. Dim dt As DataTable = ds.Tables("tblTEST")
    8. For Each cRow As DataRow In dt.Rows
    9. cRow("EXPORTIERT") = True
    10. Next
    11. Dim cmd As New OleDbCommand("UPDATE tblTEST SET EXPORTIERT = ?", conn)
    12. cmd.Parameters.Add("@P1", OleDbType.Boolean, 1, "EXPORTIERT")
    13. da.UpdateCommand = cmd
    14. da.Update(ds, "tblTEST")
    15. End Sub


    Die Tabelle tblTEST hat aber ca. 560.000 Datensätze und jeder Datensatz soll aktualisiert werden. Bis zum Befehl da.Update(ds, "tblTEST") vergehen ca.12 Sekunden. Der Befehl da.Update(ds, "tblTEST") selbst dauert auf meinem nagelneuen PC (WIN 8.1, 4GB, VB 2010) über 10 Minuten. Breche ich die Funktion nach ca. 1 Minute ab, stehen alle Änderungen wie gewünscht in der Tabelle .

    Was mache ich falsch? Gibt es eine Möglichkeit, das Problem zu umgehen?

    Danke im voraus für alle Tipps.

    Gruß Schorsch
    Geht's da nicht einfacher mit folgenden Code?

    Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. strCONLOC = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\TEST\TEST.MDB;Jet OLEDB:Database Password=TEST;Jet OLEDB:System Database=C:\TEST\TESTSYS.MDW;User ID=TEST;Password=TEST"
    3. Dim conn As New OleDbConnection(strCONLOC)
    4. Dim cmd As New OleDbCommand("UPDATE tblTEST SET EXPORTIERT = True", conn)
    5. conn.Open()
    6. cmd.ExecuteNonQuery()
    7. conn.Close()
    8. End Sub
    ist aber ungetestet ... könnte man noch mit Using austatten...
    Hallo VB1963,

    ja, natürlich, das geht auch.

    In der Realität sieht es aber so aus, dass ich die 560.000 Datensätze durchlesen muss und nach vielen verschiedenen Kriterien, die selbst nicht in der Tabelle stehen, entscheiden muss, welcher Datensatz das kennzeichen "EXPORTIERT" erhält. Zu komplex um es hier darzustellen.

    Trotzdem danke für den Tipp!

    Gruß Schorsch
    Danke, VB1963, für den Hinweis. Ich glaube aber, petaod hat Recht.

    Ich habe den Code etwas verändert, allerdings ohne das gewünschte Ergebnis:

    Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. Dim dtROW As DataRow
    3. Label1.Text = Now().ToString
    4. Label1.Refresh()
    5. strCONLOC = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\TEST\TEST.MDB;Jet OLEDB:Database Password=TEST;Jet OLEDB:System Database=C:\TEST\TESTSYS.MDW;User ID=TEST;Password=TEST"
    6. conLOC = New OleDbConnection(strCONLOC)
    7. conLOC.Open()
    8. With cmd
    9. .Connection = conLOC
    10. .CommandText = "tblTEST"
    11. .CommandType = CommandType.TableDirect
    12. End With
    13. With dadp
    14. .SelectCommand = cmd
    15. End With
    16. dadp.MissingSchemaAction = MissingSchemaAction.AddWithKey
    17. dadp.Fill(dtbl)
    18. For Each dtROW In dtbl.Rows
    19. dtROW!EXPORTIERT = True
    20. Next
    21. Label2.Text = Now().ToString
    22. Label2.Refresh()
    23. cmb = New OleDbCommandBuilder(dadp)
    24. dadp.Update(dtbl)
    25. cmd.Dispose()
    26. dadp.Dispose()
    27. dtbl.Clear()
    28. dtbl.Dispose()
    29. conLOC.Close()
    30. conLOC.Dispose()
    31. Label3.Text = Now().ToString
    32. Label3.Refresh()
    33. End Sub


    Wie bereits beschrieben, bei 1000 Datensätzen ist diese Routine kein Problem, darüber aber schon.

    Hat noch jemand eine Idee?

    Gruß Schorsch
    Hallo zusammen,

    ich habe mir nun wie folgt geholfen: Der Inhalt des Primärschlüssels der zu aktualisierenden Tabelle wird in eine temporäre Tabelle gechrieben wenn die Kriterien zum Ändern zutreffen; danach kann ich dann den SQL-Befehl ausführen, indem ich diese beiden Tabellen verknüpfe:

    SQL-Abfrage

    1. UPDATE tblTEST
    2. INNER JOIN tblTEST_AKT ON tblTEST.LFDNR = tblTEST_AKT.LFDAKT
    3. SET tblTEST.EXPORTIERT = True


    Die Folge ist eine Verkürzung der Laufzeit von 30 auf 9 Minuten. Das ist akzeptabel.

    Das Problem der "Trägheit" tritt ab ca. 16.000 zu aktualisierenden Datensätzen auf. Die Tabelle hat 30 Spalten/Felder mit jeweils ca. 10 Stellen Text. Alle Felder sind gefüllt.

    Gruß Schorsch
    Du kannst doch einfach die Änderungsverfolgung des Datasets für dich arbeiten lassen.
    Dabei darfst du aber die Rows nur auf exportiert setzen, wenn nötig. Also "Exportiert" nur da zuweisen, wo sich der neue Wert vom alten auch unterscheidet.
    Dann kannst du deinen DAtaAdapter wiederverwenden, indem du einen Commandbuilder damit erstellst.
    Allein das Erstellen des CommandBuilders generiert in deim DataAdapter ein gültiges UpdateCommand, mit dem du die Datattable updaten kannst.
    Das wäre das einfachste, und auch das übliche, wie Dataset konzipiert ist: Laden - ändern - Änderungen updaten.

    Performance ist jetzt offen: wird sehr viel exportiert, so wird auch viel geupdated, und ist vmtl. deine Lösung schneller. Sinds hingegen eher weniger Datensätze, dann ist die Ausnutzung der Änderungsverfolgung effizienter.
    Ja, das mit der Änderungsverfolgung habe ich mittlerweile auch gelesen (habe eine Woche nach einer Lösung gesucht...) und ausprobiert. Dies ist meines Erachtens auch der korrekte Weg.

    Das einzige Problem ist die Performance. Ich habe nun für mich beschlossen, jede größere Tabelle mit einem Primärkey in Form eines Feldes mit AutoWert zu versehen, damit ich große Datenmengen relativ schnell aktualisieren kann (wie oben beschrieben).

    Ich halte dieses Performanceproblem für einen Fehler bzw. eine Schwäche in ADO.NET. Allerdings weiß ich mir ja jetzt zu helfen; insoweit ok.

    Danke auf jeden Fall für den Hinweis!
    Ich glaube nicht, das es sich um eine Schwäche von ADO .NET handelt.
    Vielmehr glaube ich (aus eigener Erfahrung), dass das als Single-User entwickelte Datenhaltungssystem (ich spreche BEWUSST nicht von einer Datenbank) mit Deinen Anfordeungen schlichtweg überfordert ist. Tante Google und Onkel Bing stützen da meine Ansicht.
    Test mal aufe SQL-Server (sogar Express), und Du wirst die Performanceprobleme nicht mehr feststellen.