PerformanceHighlight of Weekly #002

Many2one LEFT JOINs promoted to INNER JOINs

The ORM now adds a hint that lets PostgreSQL turn LEFT JOINs on optional many2one fields into INNER JOINs for positive conditions. This gives the query planner more join orders to choose from.

Versions19.0
AppFramework & technical

Pull requests and commits

BranchPull requestCommit
19.0odoo/odoo#287712 ↗dfc5e84ec8 ↗

Commit message

[PERF] orm: add explicit JOIN-promotion hint for many2one LEFT JOINs

Odoo uses a LEFT JOIN when traversing an optional many2one field, since the
FK can be unset. For positive conditions, the SQL already included
`fk_col IS NOT NULL` to exclude records where the relation is empty, which
logically makes the LEFT JOIN equivalent to an INNER JOIN, but does not
trigger PostgreSQL's join promotion.

To decide whether to promote, PostgreSQL scans the WHERE clause for
predicates that cannot return TRUE when the right-side table's columns are
all NULL (as they would be on an unmatched row). `fk_col IS NOT NULL` is a
predicate on the left table, so it is invisible to that check. Table
constraints do not help either: the promotion logic (`reduce_outer_joins()`)
is purely predicate-based and does not consult them.

Adding `joined_table.id IS NOT NULL` gives the planner exactly what it
needs: a null-rejecting predicate on the right side. Once promoted to an
INNER JOIN, the planner can reorder the join freely, typically choosing to
start from the smaller lookup table rather than being forced to drive from
the large fact table and discard most rows afterward.

The predicate is a semantic no-op and acts purely as a hint: if the join
matched, the right-side `id` is by definition not NULL, so query results are
identical and there is no behavioral risk.

The `fk_col IS NOT NULL` is kept, even if there is an equivalence class
between the `id` and the `fk_col` post-promotion, because PG doesn't
evaluate cost estimation with equivalence class evaluated, only based
on the initial predicate on the table. This is impactful if the `fk_col`
predicate is highly selective.

task-6296255

My stack

Pick the versions and apps you run. Weekly digests, this week's table and All changes then show only what concerns you. Saved in this browser.

Versions
Apps
Modules