odoo-perflisted
Install: claude install-skill tuanle96/odoo-ai-skills
# Odoo performance
In Odoo, wall-clock is dominated by **SQL query count**, not Python. The ORM already batches writes, prefetches relations, and caches reads across a whole recordset — almost all slowness is *fighting* it: a `search` or `browse` inside a loop turns one query into N. **Measure the real count first**, then fix the hot path. Delegate measurement to the **`odoo-introspect`** skill — `trace_flow` reports `total_sql` and per-call `sql_count`:
```bash
odoo-ai --db <DB> trace <model> <record_id> <method> # total_sql + sql_count per call
```
**Version floor: Odoo 17/18, through Odoo 19 (current LTS).** The `_read_group` tuple API and the `flush_*` / `invalidate_*` cache methods are v16/17+; pre-16 uses `read_group` (dicts) and `flush()` / `invalidate_cache()`. Note `read_group` is **deprecated in 18.2** (use `_read_group`, or `formatted_read_group` for formatted public output), and the field aggregate attribute `group_operator` was renamed **`aggregator` in 17.2** — see `skills/odoo-introspect/references/version-matrix.md`.
## Use the built-in, don't hand-roll it
| Need | Use | Not |
|------|-----|-----|
| Count / sum / group per key | `_read_group(domain, groupby, aggregates)` | `search` + count in a loop |
| Load N records' relations | one recordset + `mapped` / prefetch | `browse(id)` per row |
| Filter / sort already-loaded recs | `recs.filtered(...)`, `recs.sorted(...)` | re-`search` with a tweaked domain |
| Update many rows the same way | `recs.write({.