Datenbank: Access • Version: 2000 • Zugriff über: ADOQuery
Access zu langsam
Hallo,
wer kann mir helfen? Ich muss jeweils 20 bis 30 Seriennummern aus einer TListBox in eine Access Datenbank übernehmen, welche sich auf dem Server befindet. Für jede Seriennummer soll ein eigener Datensatz angelegt werden. Je nach verwendeten PC geht es manchmal mit SQL-Befehlen und manchmal mit "ADODataSet.Edit / Append / Post" schneller. Prinzipiell würde ich aber SQL bevorzugen. Das nachfolgende Beispiel benötigt auf einem 1 GHz Rechner ca. 10 s für 30 Datensätze.
Delphi-Quellcode:
Wie kriege ich das schneller hin?
function TForm1.WriteSNr: Boolean;
var i: Integer; begin try for i := 0 to ListBox1.Count - 1 do begin ADOQuery4.Close; ADOQuery4.SQL.Text := 'INSERT INTO Tabelle4 (Seriennummer) ' + 'VALUES (:PSeriennummer)'; ADOQuery4.Parameters.ParamByName('PSeriennummer').Value := ListBox1.Items.Strings[i]; ADOQuery4.ExecSQL; Result := True; end; except Result := False; end; end; Vielen Dank schon mal ... |
Re: Access zu langsam
Mit diesem "kleinen" Insert solltest du über eine 100MBit Verbindung mehrere Hundert Datensätze pro Sekunde in die DB Schieben.
Das Problem liegt sicher woanders. Hast du schon mal probiert die DB testweise auf deinen lokalen PC zu legen, um Netzwerk- oder Serverprobleme auszuschließen? Hängen eventuell irgendwelche datensensitiven Komponenten an einer Datasource die mit deiner ADOQuery4 verbunden ist ? Wenn ja, dann hänge die Datasource ab oder verbaue DisableControls und EnableControls. z.B. so ...
Delphi-Quellcode:
Wenn beides nicht hilft versuche mal deine Access DB zu reparieren und zu komprimieren bzw. aktuelle JET Treiber zu installieren.
function TForm1.WriteSNr: Boolean;
var i: Integer; begin try try Result := False; // init ADOQuery4.DisableControls; // <<<< for i := 0 to ListBox1.Count - 1 do begin ADOQuery4.Close; ADOQuery4.SQL.Text := 'INSERT INTO Tabelle4 (Seriennummer) ' + 'VALUES (:PSeriennummer)'; ADOQuery4.Parameters.ParamByName('PSeriennummer').Value := ListBox1.Items.Strings[i]; ADOQuery4.ExecSQL; Result := True; end; finally ADOQuery4.EnableControls; // <<<< end; except Result := False; end; end; Sorry, was Genaueres kann ich dir erstmal nicht anbieten. 0,3 Sek pro Datensatz ist extrem zuviel und deine INSERT Function sieht OK aus. Schöne Grüße, Jens :hi: |
Re: Access zu langsam
Moin Jens,
Du darfst nicht vergessen, dass Jet nur eine Desktop DB engine ist. Er wird also _immer_ fast alle DS hin und her schieben, genauso wie er auch ständig nachschaut, ob sie geändert wurde. Und beim "Öffnen" wird das Ding tatsächlich "geöffnet" als ob es ein Dokument in Word wäre. (was natürlich darin resultiert, dass es komplett geladen wird.... :shock: ) Den Sinn von sowas kapiere ich auch nicht ganz... Entweder lokale DB, oder nicht. Solche Spielereien wie eine Jet DB auf einen Fileserver zu packen sind mir irgendwie schleierhaft... :gruebel: |
Re: Access zu langsam
da access keine serverbasierte DB ist, wird immer die gesamte DB als file hin und her kopiert - wenn das über netzwerk oder gar internet passiert, geht das natürlich umso langsamer je größer die db und je langsamer die verbindung zur freigabe der DB
|
Re: Access zu langsam
Moin moin,
also ob es durch meinen Hinweis merklich (bei 30 DS) schneller wird, ist fraglich... aber trotzdem:
Delphi-Quellcode:
1. Die Datenmenge muss bei ExecSQL nicht immer wieder geschlossen werden, da keine geöffnet wird...
function TForm1.WriteSNr: Boolean;
var i: Integer; begin try ADOQuery4.Close; ADOQuery4.SQL.Text := 'INSERT INTO Tabelle4 (Seriennummer) ' + 'VALUES (:PSeriennummer)'; ADOQuery4.Prepared := True; for i := 0 to ListBox1.Count - 1 do begin ADOQuery4.Parameters.ParamByName('PSeriennummer').Value := ListBox1.Items.Strings[i]; ADOQuery4.ExecSQL; end; Result := True; except Result := False; end; end; 2. Das SQL Statement muss nicht bei jedem Durchlauf der Schleife neu gesetzt werden... 3. Prepared auf True setzen (Ob das bei Access auch was nützt??? ... hab keine Ahnung) 4. Result kann nach der Schleife gesetzt werden, da ja im Fehlerfall eh False PS: Punkt 4 bringt dir bestimmt die erhoffte Geschwindigkeit :???: |
Re: Access zu langsam
Zitat:
OK, dann teste es doch mal so ...
Delphi-Quellcode:
Damit öffnest du die DB nur einmal.
Result:=true;
try ADOQuery4.Close; ADOQuery4.SQL.Clear; for i := 0 to ListBox1.Count - 1 do begin ADOQuery4.SQL.Add := 'INSERT INTO Tabelle4 (Seriennummer) ' + 'VALUES ('+ListBox1.Items.Strings[i]+')'; end; ADOQuery4.ExecSQL; Except On E:Exception do begin Result :=false; showmessage('Beim Speichern ist folgender Fehler aufgetreten: '+#13#10+e.Message); end; end; |
Re: Access zu langsam
Zitat:
Im Übrigen lässt sich bei Access eine erhebliche Geschwindigkeitssteigerung erzielen, wenn man die Cursor-Location von Clientsided auf Serversided umstellt. Generell kann man schon sagen, dass man mit Access auch bei gemeinsamen Zugriffen im Netz gut arbeiten kann, solange die Anzahl von Datensätzen pro Tabelle nicht mehr als einige (wenige) Zehntausend sind. Und irgendwelche umfangreichen Batch-Jobs, die z.B. 10.000 Datensätze neu einfügen oder löschen oder sonst was - die lässt man üblicherweise sowieso nicht tagsüber laufen, sondern eben nachts im Rahmen von automatisch ausgeführten Jobs. |
Re: Access zu langsam
Hallo zusammen,
erst mal vielen Dank für die zahlreichen Hinweise, die werde ich jetzt mal austesten. Übrigens, um exakte Zeiten zu ermitteln nutze ich die Kompo "HPCounter", funktioniert super, Auflösung ist 1 Mikrosekunde. Ich möchte mal meine Anwendung präzisieren: Über einen Handscanner werden Seriennummern verschiedener Produkte in eine ListBox geschrieben und dann in die DB übernommen. Die DB besteht aus 3 verknüpften Tabellen. In der 1. sind die verschiedenen Produkte, in der 2. die Seriennummern der jeweiligen Produkte und in der 3. die Infos zur jeweiligen Seriennummer. Um die ganze Sache zu beschleunigen schreibe ich die ListBox erst mal in eine Hilfstabelle die immer leer ist. Mit je einem SQL-Befehl werden alle Seriennummern in die Tabelle 2 und alle Infos dazu in Tabelle 3 übernommen. Das bringt schon mal ca. 60 bis 70 % Zeitersparnis gegenüber dem direkten Schreiben in Tabelle 2 und 3. Der Flaschenhals ist, die 20 ... 30 Seriennummern von der ListBox in die Hilfstabelle zu bringen. Was ich mir noch überlegt habe ist, für die Hilfstabelle eine separate lokale Datei zu verwenden. |
Re: Access zu langsam
Ich noch mal ...
Hab alles getestet, allerdings nur lokal auf meinem 1,4 GHz P4 mobile. Geschwindigkeitszuwachs gleich Null. Für 30 Datensätze brauche ich genau 1,6 Sekunden. Werde es morgen mal mit der DB auf dem Server probieren. Was allerdings nicht funktioniert ist dieser Vorschalg :
Delphi-Quellcode:
War bei dieser Sache sowieso skeptisch, da werden doch einfach nur alle SQL-Kommandos hintereinander geschrieben.
Result:=true;
try ADOQuery4.Close; ADOQuery4.SQL.Clear; for i := 0 to ListBox1.Count - 1 do begin ADOQuery4.SQL.Add := 'INSERT INTO Tabelle4 (Seriennummer) ' + 'VALUES ('+ListBox1.Items.Strings[i]+')'; end; ADOQuery4.ExecSQL; Except On E:Exception do begin Result :=false; showmessage('Beim Speichern ist folgender Fehler aufgetreten: '+#13#10+e.Message); end; end; Tschau |
Re: Access zu langsam
Zitat:
Das nennt sich BULK INSERT Script. Bei erwachsenen SQL Servern wird jeder Befehl mit einem GO (als "Befehlsende") abgeschicht. Access verwendet anstatt des "go" ein Semikolon zum abschicken des Befehls. Hätte also durchaus klappen können :roll: Da ich den "nicht funktionierenden" Code nicht auf mit sitzen lassen wollte, habe ich jetzt eine Weile gegoogelt und lernen dürfen, das ACCESS keine BULK INSERTS unterstützt. :kotz: Tut mir Leid falls du dir dadurch unnötig Arbeit gemacht hast, aber der Weg wäre imho bei jeder anderen DB richtig gewesen. Schöne Grüße, Jens :hi: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz