Alle Artikel zu #visual basic for applications


Datenbankzugriffe beschleunigen in Visual Basic

Seit ich bei E.ON den Programmcodeblock zum Update der Datenbank geschrieben habe, stört mich die irre lange Ausführungszeit. Es geht dabei darum, von ca 300.000 Datensätzen anhand zweier Felder zu prüfen, ob sie bereits in der Datenbank sind, und ggf. Ergänzungen vorzunehmen. Beide Felder enthalten numerische Werte.

Bisher habe ich dazu ein Recordset geladen, was alle Datensätze in der Tabelle enthält, und dann eine Schleife geschrieben die alle eventuell zu ergänzenden Datensätze durchläuft. Darin wurde dann jedesmal ein Filter auf das Recordset gesetzt, und entweder blieb dann genau ein Datensatz über oder keiner, wenn's keiner war, musste ich den ergänzen. Das hat natürlich immer ewig gedauert, so etwa 1,5h, denn je nachdem wie intelligent Access da arbeitet, waren das 300.000 Durchläufe - für jeden der 300.000 Datensätze.

Jetzt habe ich einfach mal, in der Hoffnung den Vorgang vielleicht wenigstens auf ein Drittel reduzieren zu können, eine ganz andere Methode gewählt: Ich erstelle ein zweidimensionales Boolean-Array (für jedes Feld eine Dimension) mit den minimalen und maximalen Werten der Fehler als Grenzen (... To ..., ... To ... mit ReDim, Dim lässt da nur konstante Werte zu, meine sind aber dynamisch, da es sich um IDs einer anderen Datenbanktabelle handelt). Dann durchlaufe ich das Recordset, bei dem ich vorher immer den Filter setzen musste, einmal komplett und setze dabei im Array alle Felder, die durch das Recordset angegeben werden, auf true (meinarray (rs("feld1"), rs("feld2")) = true). So erhalte ich ein Array, in dem die vorhandenen Felder markiert sind.

Das Recordset wird jetzt schon nicht mehr benötigt. Der nächste Schritt durchläuft alle möglichen Werte für die beiden Felder (verschachtelte Schleife) und prüft dabei, ob der Wert im Array an der gerade durch die Schleifen gegebenen Stelle false ist. Falls ja, wird das Wertepaar in der Datenbank ergänzt. Dadurch, dass das Array vom minimalen zum maximalen Wert der Felder dimensioniert ist, gibt es, wenn die Tabelle, der die IDs entstammen, nicht durchgehend ist (Datensätze gelöscht...), mehr Positionen im Array als abgefragt werden, die dann auch auf false stehen. Macht aber nix, da die Schleife, in der die Ergänzungen vorgenommen werden, mit den tatsächlich eingetragenen Werten arbeitet und so keine IDs eingetragen werden, die es gar nicht mehr gibt.

Ergebnis: Statt 1,5 Stunden dauert der Vorgang jetzt vielleicht noch 20 Sekunden... Hätte nicht gedacht, dass es SO ineffizient ist, mit einem Recordset zu arbeiten. Anscheinend wird doch keine Kopie im Programm angelegt, sondern immer direkt auf die Datenbank zugegriffen.

Was vielleicht noch anzumerken ist, wäre die Tatsache, dass ich beim Anlegen des Recordsets nebenbei den Zugriffsmodus auf "adLockBatchOptmistic" gesetzt habe, was sich vom Namen her passender anhört als "adLockReadOnly", welches ich zuvor verwendet hatte. Die Beschreibung sagte was anderes, deshalb hab ich das zuvor nicht benutzt. Was genau jetzt den größeren Geschwindigkeitsvorteil ausgemacht hat, weiß ich nicht, ist mir aber eigentlich auch egal :D



Unerwartet

Ohne Worte...