DE · AT · CHAnleitung

Odoo ist langsam: Ursachen finden und beheben

Rechtsstand: · Aktualisiert:

Gilt für: Odoo 20.0 Community und Enterprise; Odoo Online, Odoo.sh, eigene Installation (On-Premise); PostgreSQL 18; unabhängig von Modulen und Lokalisierung

Kurz gesagt

Langsames Odoo hat drei Schichten: die Darstellung im Browser, die Arbeit der Odoo-Prozesse und die Abfragen in PostgreSQL. Messen Sie zuerst Antwortzeit und Auslastung, grenzen Sie die Aktion mit dem Profiler ein und prüfen Sie danach die Abfrage mit EXPLAIN (ANALYZE, BUFFERS). Odoo-Online-Datenbanken lassen sich nicht profilieren; auf einer eigenen Installation zählen zusätzlich Worker, Arbeitsspeicher und die Grenzwerte je Worker.

Das Wichtigste

  • Erst messen: Antwortzeit, abgelehnte Anfragen und Auslastung je Hostingmodell, nicht die Zahl der Konten.
  • Odoo 20.0 bringt einen Profiler; Odoo-Online-Datenbanken lassen sich laut Dokumentation nicht profilieren.
  • Ein Worker trägt rund sechs gleichzeitige Nutzer; zusätzliche Worker beheben keinen langsamen Vorgang.
  • Auf Odoo.sh stehen im Reiter Logs die Datei pg_slow_queries.log und im Reiter Monitor die Lastkurven.
  • EXPLAIN (ANALYZE, BUFFERS) vergleicht Schätzung und Wirklichkeit und zeigt, ob eine Sortierung auf die Platte ging.

Langsamkeit ist ein Befund, keine Ursache: Derselbe Satz „die Rechnungsliste ist langsam” kann zu wenige Prozesse für die gleichzeitigen Zugriffe meinen, eine geplante Aktion um dieselbe Zeit, eine Abfrage ohne Index oder ungebündelte Dateien im Browser. Dieses Vorgehen trennt die drei Schichten und ordnet jedem Symptom eine Messung zu.

Was Sie vorab brauchen

  • Die Zugänge Ihres Hostingmodells: eigene Installation — Konfigurationsdatei, Protokoll, PostgreSQL-Zugang, Serverkennzahlen; Odoo.sh — Reiter Monitor und Logs, Webshell; Odoo Online — Verwaltung im Odoo-Konto.
  • Einen wiederholbaren Fall: Aktion, Nutzerkreis, Tag und Uhrzeit in UTC, weil die technischen Protokolle von Odoo.sh in UTC laufen.
  • Einen Ausgangswert als Zahl, etwa die durchschnittliche Antwortzeit aus dem Monitor von Odoo.sh.
  • Rechte für EXPLAIN; für Summen über alle Abfragen das Modul pg_stat_statements in shared_preload_libraries (Neustart nötig).

Diagnosebaum: vom Symptom zur Ursache

Der Baum ist die Prüfreihenfolge dieser Redaktion, keine Aussage über Häufigkeiten.

Symptom Erste Messung Mögliche Ursache Weiter bei
Alle Seiten langsam, alle Nutzer betroffen Antwortzeit, abgelehnte Anfragen, Prozessorlast zu wenige Prozesse oder Kerne, Mehrthread-Betrieb Schritt 2 und 3
Eine Liste, ein Bericht oder das Speichern ist langsam Profiler auf diese Aktion Abfrage oder QWeb-Bericht aus einem Modul Schritt 4 und 7
Die Seite braucht lange bis zu den Daten Antwortzeit, Adresszeile im Browser ungebündelte Dateien (debug=assets), Odoo liefert statische Dateien selbst Schritt 8
Jeden Tag zur selben Minute Lastkurve und Protokoll um diese Zeit geplante Aktion, Mail, Import oder Sicherung Schritt 5
Ein Vorgang bricht ab, danach läuft es wieder Protokoll um den Abbruch, Speicher je Worker Zeit- oder Speichergrenze, Worker beendet Schritt 3 und 8
Mit der Datenmenge schleichend langsamer Dauer der Abfrage, EXPLAIN (ANALYZE, BUFFERS) fehlender Index, veraltete Statistik, Sortierung auf die Platte Schritt 6 und 7

Schritt für Schritt: messen, eingrenzen, beheben

Schritt 1: Fall und Zeitpunkt festhalten

Schreiben Sie auf, was langsam ist und was nicht: eine bestimmte Liste, ein Bericht, das Speichern, die Anmeldung oder die gesamte Oberfläche. Halten Sie fest, ob ein Nutzer oder alle betroffen sind, ob es dauerhaft oder zu bestimmten Zeiten auftritt und seit wann. Ergebnis: eine Notiz wie „14.10.2026, 09:12 UTC, Verkaufsaufträge, Liste mit 20.000 Zeilen, alle Nutzer, seit dem Datenimport am 13.10.”

Schritt 2: Antwortzeit und Auslastung messen

Bei Odoo.sh liefert der Reiter Monitor die Lastkurven: Arbeitsspeicher der Worker und der Datenbank, Prozessorlast getrennt nach HTTP-Workern, geplanten Aktionen und Datenbankprozessen, dazu Anfragen je Sekunde, abgelehnte Anfragen und die durchschnittliche Antwortzeit in Millisekunden. Ältere Abschnitte sind verdichtet; Einzelheiten zeigt der jüngere Verlauf.

Auf einer eigenen Installation messen Sie Prozessorlast, Arbeitsspeicher und Antwortzeit selbst. Das Konfigurationsbeispiel der Bereitstellungsseite rechnet mit vier Prozessorkernen und acht Threads und prüft die CPU-Last zwischen 7 und 7,5.

Schritt 3: Anfragen und Kapazität vergleichen

Für eine eigene Installation gelten die Faustregeln der Bereitstellungsseite: Prozesse = Prozessorkerne × 2 + 1, ein Worker trägt rund sechs gleichzeitige Nutzer. Prüfen Sie, ob die Option workers gesetzt ist: Auf dem Vorgabewert 0 läuft der Mehrthread-Server, den die Dokumentation für Entwicklung und Demonstrationen nennt; wegen der Python-Beschränkung (GIL) nutzt er die Hardware nicht aus.

Mehr Prozesse beheben einen langsamen Vorgang nicht: Die Odoo.sh-Dokumentation hält fest, dass zusätzliche Worker nur die Zahl gleichzeitiger Verbindungen erhöhen; bleibt es langsam und liegt es nicht an Ihren Anpassungen, nennt sie den Odoo-Support. Für die Größenwahl siehe Odoo-Server dimensionieren.

Schritt 4: Die langsame Aktion mit dem Profiler isolieren

Odoo 20.0 enthält einen Profiler, der ausgeführte Abfragen und Aufrufketten aufzeichnet (die Dokumentation beschriftet ihn englisch). Er wird zuerst datenbankweit freigeschaltet — im Entwicklermodus über die Schaltfläche Enable profiling oder unter Einstellungen (Settings) im Bereich Performance im Feld Enable profiling until — und danach für die eigene Sitzung eingeschaltet. Standardmäßig zeichnen die Sammler Record sql und Record traces auf; der SQL-Sammler nimmt jede Abfrage im laufenden Thread samt Aufrufkette auf, der periodische Sammler in kurzen Abständen die Aufrufkette. Die Aufnahmen liegen als Datensätze des Modells ir.profile je Sitzung vor; die Ansichten Combined, sql (no gap) und sql (density) trennen den SQL-Anteil vom Python-Anteil.

Zwei Grenzen nennt dieselbe Seite: Odoo-Online-Datenbanken lassen sich nicht profilieren, und das Profiling kostet selbst Ausführungszeit.

Schritt 5: Zeitgesteuerte Last prüfen

Last entsteht auch ohne Nutzeraktion. Bei Odoo.sh trennt die Prozessorkurve geplante Aktionen und eingehende Mails von den HTTP-Workern. Sehen Sie dort eine Spitze zur gemeldeten Uhrzeit, prüfen Sie die geplanten Aktionen im technischen Menü sowie die Zeitpunkte von Importen, Sicherungen und Serienmails.

Bei Odoo.sh laufen geplante Aktionen nach bestem Bemühen, und nach der Dokumentation ist nicht mit einer Ausführung häufiger als alle fünf Minuten zu rechnen; lange Aktionen sollen in kleinen Stapeln arbeiten und nach jedem Stapel festschreiben. Auf einer eigenen Installation bestimmt die Option max-cron-threads (Vorgabe 2), wie viele Threads oder Prozesse für Cron-Aufgaben bereitstehen — Threads im Mehrthread-Betrieb, Prozesse im Mehrprozess-Betrieb; im Mehrprozess-Betrieb kommen sie zu den HTTP-Workern hinzu. Welche Regeln zeitgesteuert laufen, beschreibt Automatisierungsregeln in Odoo.

Schritt 6: Die Datenbank messen und die langsame Abfrage finden

Sie brauchen zuerst die Abfrage, die Zeit kostet. Auf Odoo.sh führt der Reiter Logs die Datei pg_slow_queries.log mit Abfragen, die ungewöhnlich lange brauchen. Auf einer eigenen Installation setzen Sie log_min_duration_statement in der postgresql.conf auf einen Wert in Millisekunden; -1 (Vorgabe) schaltet die Protokollierung ab, 0 protokolliert jede Anweisung. pg_stat_activity zeigt je Serverprozess den Zustand, die laufende Abfrage und mit den Spalten wait_event_type und wait_event das Warteereignis. Lock ist nur einer von mehreren Wartetypen (daneben etwa IO, LWLock und Client), und eine Sperre auf eine Tabelle zeigt sich als Warteereignis vom Typ Lock (etwa wait_event relation). Eine Sperre ist erst dann die Ursache und nicht Rechenzeit, wenn ein Prozess nachweislich auf eine solche Sperre wartet; dass mehrere Prozesse auf dieselbe Tabelle warten, belegt sie allein nicht.

Für Summen über alle Abfragen dient pg_stat_statements (Laden über shared_preload_libraries, Neustart nötig, Spalte total_exec_time). Pläne langsamer Abfragen schreibt auto_explain mit, sobald auto_explain.log_min_duration gesetzt ist; auto_explain.log_analyze ist standardmäßig aus.

Schritt 7: Die Abfrage mit EXPLAIN erklären

Mit EXPLAIN (ANALYZE, BUFFERS) führt PostgreSQL die Abfrage aus und stellt den geschätzten Werten die tatsächlichen gegenüber. Weichen die Zeilenzahlen stark voneinander ab, passen die Statistiken nicht zur Verteilung; dann hilft ANALYZE, für korrelierte Spalten zusätzlich eine erweiterte Statistik. Ein sequenzieller Scan über eine große Tabelle (im Plan Seq Scan) kann auf einen fehlenden Index hinweisen; fehlt jeder Index, ist er die einzige Möglichkeit. Er ist aber kein Beweis: PostgreSQL wählt ihn auch dann, wenn eine Abfrage viele Zeilen braucht, weil das separate Holen der Zeilen über den Index teurer ist als das Lesen der Seiten der Reihe nach. Die Kosten im Plan sind willkürliche Einheiten und keine Zeitangabe; vergleichen Sie die geschätzten mit den tatsächlichen Zeilenzahlen, bevor Sie einen Index anlegen. Der Sort-Knoten nennt die Sortiermethode und ob sie im Arbeitsspeicher oder auf der Platte lief; ging sie auf die Platte, ist work_mem der Anhaltspunkt (Vorgabe 4 MB, je Sortier- oder Hash-Operation und je Sitzung mehrfach möglich).

In eigenen Modulen setzen Felder einen Index über index=True. Die Dokumentation warnt zugleich, jedes Feld zu indizieren: Indizes kosten Platz und belasten jeden Einfüge-, Änderungs- und Löschvorgang.

Schritt 8: Wartung, Grenzwerte und statische Dateien prüfen

  • Datenbankwartung. Ein UPDATE oder DELETE gibt den Platz einer Zeile nicht sofort frei; VACUUM macht ihn für neue Zeilen nutzbar, sonst wächst die Tabelle. In der Vorgabekonfiguration ist autovacuum eingeschaltet; für partitionierte Tabellen führt es kein ANALYZE der Elterntabelle aus.
  • Arbeitsspeicher der Datenbank. shared_buffers steht voreingestellt auf 128 MB. Als Startwert nennt die PostgreSQL-Dokumentation ein Viertel des Arbeitsspeichers, und zwar für einen ausschließlich als Datenbankserver genutzten Rechner mit mindestens 1 GB Arbeitsspeicher; läuft Odoo auf demselben Server, muss dessen Arbeitsspeicher davon abgehen. Unter 1 GB empfiehlt dieselbe Stelle einen kleineren Anteil, damit Platz für das Betriebssystem bleibt, und mehr als 40 % bringen nach ihrer Einschätzung kaum mehr. Der Wert ändert sich nur beim Start des Servers.
  • Grenzwerte je Worker (Mehrprozess-Betrieb, workers ungleich 0). Auf einer eigenen Installation beendet der Prozessverwalter einen Worker, der länger als 120 Sekunden Wanduhrzeit braucht (Vorgabe limit_time_real), und einen Worker über 2048 MiB weichem beziehungsweise 2560 MiB hartem Arbeitsspeicher. Prüfen Sie, welche Werte in Ihrer Konfigurationsdatei stehen.
  • Statische Dateien. Odoo liefert Dateien aus den Modulen und Anhänge selbst aus; die Dokumentation nennt das für die Leistung nicht ideal und empfiehlt, statische Dateien vom Webserver auszuliefern und Anhänge über X-Sendfile oder X-Accel (--x-sendfile) zu übergeben.
  • Browser. JavaScript und Stilvorlagen werden gebündelt und minifiziert, außer im Modus debug=assets; steht ?debug=assets in der Adresszeile, lädt der Browser ungebündelte Dateien. Setzen Sie vor der Beurteilung ?debug=0.

So prüfen Sie das Ergebnis

Messen Sie dieselbe Kennzahl wie am Anfang, mit derselben Aktion und zur gleichen Tageszeit: die durchschnittliche Antwortzeit, die Dauer einer Abfrage oder die Zeilenzahlen im Plan. Schalten Sie den Profiler vorher ab.

shared_buffers wirkt erst nach einem Start des Datenbankservers; log_min_duration_statement und work_mem lassen sich für eine Sitzung setzen. Prüfen Sie einen neuen Index mit EXPLAIN (ANALYZE, BUFFERS) derselben Abfrage. Solche Änderungen gehören zuerst in eine Kopie der Datenbank, siehe Testumgebung für Odoo.

Wenn etwas nicht klappt

Beobachtung Ursache Was tun
Die Schaltfläche Enable profiling fehlt Entwicklermodus nicht aktiv oder Datenbank auf Odoo Online Entwicklermodus einschalten; auf Odoo Online ist Profiling ausgeschlossen
Das Profiling zeigt fast nur den SQL-Sammler Der SQL-Sammler von Odoo kostet bei vielen kleinen Abfragen selbst Zeit Für die Daueranalyse den periodischen Sammler nutzen
Ein Index ist angelegt, der Plan nutzt ihn nicht Für diese Abfrage kann der sequenzielle Scan billiger sein, etwa wenn sie viele Zeilen braucht; die Kostenschätzung ist keine Zeitangabe Plan mit EXPLAIN (ANALYZE, BUFFERS) prüfen, geschätzte und tatsächliche Zeilenzahlen vergleichen, Statistik aktualisieren
EXPLAIN ANALYZE verändert Daten Die Option ANALYZE führt die Anweisung aus Schreibende Anweisungen in der Testumgebung prüfen

Wann Sie Hilfe holen sollten

Bei Odoo.sh nennt die Dokumentation den Odoo-Support, wenn Vorgänge langsam bleiben und Ihre Anpassungen nicht die Ursache sind; die Webshell des Zweigs enthält psql. Liegt die Ursache in eigenen oder gekauften Modulen, sind der Entwickler oder Ihr Odoo-Partner die richtige Stelle.

Bei Odoo Online lässt sich nicht profilieren. Die Dokumentation 20.0 beschreibt für Odoo Online die Verwaltung im Datenbankmanager; wo er nicht weiterhilft — etwa bei einer Sicherung, die zu groß zum Herunterladen ist, bei einer zusätzlichen Kopie über der Grenze von fünf Duplikaten oder bei einer Eigentumsübertragung — verweist dieselbe Seite auf den Odoo-Support und ein Support-Ticket. Für die laufende Beobachtung siehe Odoo überwachen.

Häufige Fragen

Woran erkenne ich, ob mehr Serverleistung hilft?

An den abgelehnten Anfragen und der durchschnittlichen Antwortzeit, wenn die Auslastung steigt. Steigen beide mit der Nutzerzahl und sinken nach mehr Arbeitsspeicher oder mehr Prozessen, war die Kapazität der Engpass. Bleibt ein einzelner Vorgang langsam, während die Auslastung niedrig ist, liegt es an einer Abfrage oder am Code; die Odoo.sh-Dokumentation schreibt, dass zusätzliche Worker nur mehr gleichzeitige Verbindungen erlauben.

Kann ich den Profiler auf einer Odoo-Online-Datenbank nutzen?

Nein. Die Performance-Seite der Dokumentation 20.0 hält ausdrücklich fest, dass sich Odoo-Online-Datenbanken nicht profilieren lassen. Für Odoo Online beschreibt die Dokumentation 20.0 im Kapitel Odoo Online die Verwaltung im Datenbankmanager (Domainnamen, Tags, Ausblenden, Verwalten, Pläne, Upgrade, Umbenennen, Duplizieren, Sicherung herunterladen, Admin-Aktivitätsprotokoll) und die Webdienste; Leistungskennzahlen nennt sie dort nicht. Kennzahlen zur Antwortzeit und Auslastung liefert auf Odoo.sh der Reiter Monitor; auf einer eigenen Installation kommen Protokoll und PostgreSQL-Zugang hinzu.

Darf ich EXPLAIN ANALYZE auf der Produktivdatenbank ausführen?

Nur für lesende Anweisungen. EXPLAIN mit der Option ANALYZE führt die Anweisung tatsächlich aus; bei INSERT, UPDATE oder DELETE verändert sie damit Daten. Prüfen Sie schreibende Anweisungen in der Testumgebung. Die Messwerte aus EXPLAIN ANALYZE enthalten außerdem keine Netzwerkzeit, weil keine Zeilen an einen Client gehen.

Warum dauert eine Liste erst nach einem Jahr im Betrieb so lange?

Weil Abfragen mit der Datenmenge wachsen. Fehlt ein Index oder passt die Statistik nicht mehr zur Verteilung, liest PostgreSQL Tabellen vollständig oder sortiert auf die Platte. Prüfen Sie den Plan mit EXPLAIN (ANALYZE, BUFFERS), lassen Sie ANALYZE laufen und planen Sie die Wartung ein. Indizes kosten Platz und belasten jeden Schreibvorgang; indizieren Sie nur Felder, die gesucht oder sortiert werden.

Quellen

  1. Performance (Odoo 20.0, Entwicklerdokumentation): Profiling, Enable the profiler, Analyse the results, Collectors, Performance pitfalls, Batch operations, Reduce the algorithmic complexity, Use indexesOdoo S.A., Dokumentation · abgerufen am
  2. System configuration (Odoo 20.0, Bereitstellungsseite): Builtin server, Worker number calculation, memory size calculation, Configuration sample, PostgreSQL, Serving static files and attachmentsOdoo S.A., Dokumentation · abgerufen am
  3. Command-line interface (Odoo 20.0): Abschnitte Logging und Multiprocessing (--workers, --limit-memory-soft, --limit-memory-hard, --limit-time-cpu, --limit-time-real, --limit-request, --max-cron-threads, --log-sql, --x-sendfile)Odoo S.A., Dokumentation · abgerufen am
  4. Odoo.sh Branches (Odoo 20.0): Abschnitte Monitor (Metrics, HTTP) und LogsOdoo S.A., Dokumentation · abgerufen am
  5. Odoo.sh Settings (Odoo 20.0): Abschnitt Database workersOdoo S.A., Dokumentation · abgerufen am
  6. Odoo.sh Advanced (Odoo 20.0): Abschnitte Database shell und Scheduled actionsOdoo S.A., Dokumentation · abgerufen am
  7. Odoo Online (Odoo 20.0, Kapitel Database management): Datenbankmanager (Domain Names, Tags, Hide, Manage, Switch plans, Upgrade, Rename, Duplicate, Download Backup, View Admin Activity Logs, Transfer Ownership, Delete) und Web Services (Databases list, Audit logs)Odoo S.A., Dokumentation · abgerufen am
  8. Developermodus (Odoo 20.0, deutsche Fassung): Aktivierung, ?debug=1, ?debug=assets, EntwicklertoolsOdoo S.A., Dokumentation · abgerufen am
  9. Assets (Odoo 20.0, Frontend-Referenz): Einleitung und Bundles (Minifizierung außerhalb des Modus debug=assets)Odoo S.A., Dokumentation · abgerufen am
  10. Release Notes: Version 20, veröffentlicht im September 2026Odoo S.A. · abgerufen am
  11. PostgreSQL 18, 14.1 Using EXPLAIN (EXPLAIN Basics, EXPLAIN ANALYZE, Caveats)PostgreSQL Global Development Group · abgerufen am
  12. PostgreSQL 18, 14.2 Statistics Used by the PlannerPostgreSQL Global Development Group · abgerufen am
  13. PostgreSQL 18, 19.4 Resource Consumption (shared_buffers, work_mem)PostgreSQL Global Development Group · abgerufen am
  14. PostgreSQL 18, 19.8 Error Reporting and Logging (log_min_duration_statement)PostgreSQL Global Development Group · abgerufen am
  15. PostgreSQL 18, 24.1 Routine Vacuuming (Recovering Disk Space, Autovacuum Daemon)PostgreSQL Global Development Group · abgerufen am
  16. PostgreSQL 18, 27.2 The Cumulative Statistics System (27.2.3 pg_stat_activity, Table 27.4 Wait Event Types: Lock, LWLock, IO, Client)PostgreSQL Global Development Group · abgerufen am
  17. PostgreSQL 18, F.32 pg_stat_statementsPostgreSQL Global Development Group · abgerufen am
  18. PostgreSQL 18, F.4 auto_explainPostgreSQL Global Development Group · abgerufen am