Wenn der Bericht zu lange lädt
Du klickst auf „Bericht öffnen“.
Und wartest.
Und wartest.
Access hängt nicht.
Die SQL-Abfrage ist einfach zu langsam.
Ursachen? Viele.
Lösungen? Gibt’s.
Ich zeig Dir, wie ich rangehe.
1. Kein SELECT *
SELECT * ist bequem.
Aber tödlich für die Performance.
Beispiel:
SELECT * FROM tblRechnung WHERE Jahr = 2024
Access lädt alle Felder.
Auch Memo-Felder. Auch Anhänge.
Besser:
SELECT Rechnungsnummer, Datum, BetragNetto FROM tblRechnung WHERE Jahr = 2024
Nur das, was Du wirklich brauchst.
Alles andere bremst nur.
2. Indexe prüfen – und setzen
Ohne Index scannt Access die ganze Tabelle.
So prüfe ich per VBA:
Sub ZeigeIndexe(tabName As String)
Dim tdf As TableDef
Dim idx As Index
Set tdf = CurrentDb.TableDefs(tabName)
For Each idx In tdf.Indexes
Debug.Print idx.Name, idx.Fields
Next idx
End Sub
Wenn z. B. Jahr
nicht indiziert ist, dauert jede WHERE-Klausel länger.
Dann:
CurrentDb.Execute "CREATE INDEX idx_Jahr ON tblRechnung (Jahr)"
Hilft sofort.
Aber: Nicht zu viele Indexe – sonst bremst das beim Schreiben.
3. Abfragen verschachtelt? Entkoppeln.
Komplexe Berichte nutzen oft Unterabfragen.
Beispiel:
SELECT * FROM
(SELECT KundeID, SUM(Betrag) AS Umsatz FROM tblRechnung GROUP BY KundeID) AS Umsatz
INNER JOIN tblKunde ON Umsatz.KundeID = tblKunde.KundeID
Das ist schwer zu optimieren.
Besser: Zwei Abfragen.
qryUmsatzKunde
- Bericht nutzt
qryUmsatzKunde
direkt
Das entlastet Access.
Und Du kannst jede Abfrage einzeln testen.
4. WHERE statt HAVING
Viele nutzen HAVING, obwohl es nicht nötig ist:
SELECT KundeID, SUM(Betrag) AS Gesamt FROM tblRechnung
GROUP BY KundeID
HAVING SUM(Betrag) > 1000
Besser:
SELECT KundeID, SUM(Betrag) AS Gesamt FROM tblRechnung
WHERE Betrag > 0
GROUP BY KundeID
HAVING SUM(Betrag) > 1000
WHERE filtert vor dem Aggregat.
HAVING filtert nachher.
Großer Unterschied in der Laufzeit.
5. Recordsets statt gebundene Berichte
Gebundene Berichte können langsam laden, wenn die Abfrage komplex ist.
Ich lade die Daten lieber per VBA vor.
Public Sub BerichtMitRecordset()
Dim rs As DAO.Recordset
Dim rpt As Report
Set rs = CurrentDb.OpenRecordset("qrySchnelleDaten", dbOpenSnapshot)
DoCmd.OpenReport "rptUmsatz", acViewPreview, , , acHidden
Set rpt = Reports("rptUmsatz")
Set rpt.Recordset = rs
rpt.Visible = True
End Sub
Das macht vor allem bei Berichten mit Parametern Sinn.
Performance steigt. Stabilität auch.
6. Temporäre Tabellen nutzen
Wenn die Datenmenge groß ist, splitte ich die Schritte.
CurrentDb.Execute "DELETE FROM tmpUmsatz"
CurrentDb.Execute "INSERT INTO tmpUmsatz " & _
"SELECT KundeID, SUM(Betrag) AS Gesamt FROM tblRechnung " & _
"GROUP BY KundeID"
Bericht läuft dann nur noch gegen tmpUmsatz
.
Schnell. Kein Rechnen mehr zur Laufzeit.
7. SQL analysieren per Performance-Zeitmessung
Ich messe Abfragezeiten in VBA:
Sub MesseAbfragezeit()
Dim t1 As Single, t2 As Single
Dim rs As DAO.Recordset
t1 = Timer
Set rs = CurrentDb.OpenRecordset("qryLangsam", dbOpenSnapshot)
t2 = Timer
Debug.Print "Abfragezeit: " & Format(t2 - t1, "0.000") & " Sekunden"
rs.Close
End Sub
Alles über 0,5 Sekunden schaue ich mir an.
Und zerlege es, bis es schnell ist.
8. Backend: SQL Server statt Jet
Wenn die Datenbank groß wird (>1 GB), reicht Access nicht mehr.
Dann splitte ich:
- Access-Frontend bleibt
- Tabellen im SQL Server (per ODBC)
Abfragen laufen dort schneller.
Du kannst mit Views, Indexen und Stored Procedures arbeiten.
Und brauchst keinen Umweg über lokale Abfragen mehr.
Schrauben statt schimpfen.
Langsame Berichte sind kein Schicksal.
Meist sind es nur kleine Dinge, die bremsen.
SELECT *
Keine Indexe
Falsche Aggregation
Ich schau mir die SQL immer an.
Und dann wird’s schnell.
Wie’s sein soll.
Keine Antworten