Join elimination with and without an enforced constraint
Run a real systemNeeds Docker, Python
Problem
A join that contributes no columns can sometimes be removed. A LEFT JOIN to a unique key can never add or remove rows from the left side, so if nothing is selected from the right side, the engine can drop it. An inner join can remove rows (orders whose store does not exist), so dropping it is safe only if a foreign key guarantees every order has a store. Engines that let you declare constraints without enforcing them (RELY, NOT ENFORCED) will use them for this rewrite, and give a different answer when the data breaks the promise.
Create orders(store_id) and stores(id PRIMARY KEY), with a foreign key from orders.store_id to stores.id. Check EXPLAIN for SELECT o.order_id FROM orders o LEFT JOIN stores s ON s.id = o.store_id. Then repeat with an inner join. PostgreSQL has no declared-but-unenforced constraints, so the script shows the consequence by hand: it drops the foreign key, inserts an order for a store that does not exist, and compares the inner join's count with the count a join-free plan would give.
The question. Which joins does PostgreSQL remove, and what would removing a join on an unenforced key do to the answer?
Predict
PostgreSQL removes a left join to a unique key when nothing is selected from it. With a declared-but-unenforced constraint and a row that violates it, the answer changes when the join is removed.
Run it
1Install uv once. It fetches Python and the lab's packages for you. This lab also runs a real system, so you need Docker.
Terminal curl -LsSf https://astral.sh/uv/install.sh | sh2Get the script. It is the whole lab: read it, then download it.
View the codeHide the code
join-elimination-with-and-without-an.py # /// script # requires-python = ">=3.10" # dependencies = ["psycopg[binary]"] # /// # Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT # https://thedataengineering.com/lab-code/LICENSE.txt """Join elimination, with and without a constraint. PostgreSQL: orders and stores with a primary key on stores.id and a foreign key from orders.store_id. A LEFT JOIN that selects nothing from stores is removed from the plan; an INNER JOIN is not. Then the trap of trusting a constraint that is not enforced, shown by hand: an order whose store does not exist makes the inner join and the join-free query give different counts. Needs the PostgreSQL service from the compose file (port 55706). """ import argparse, json import psycopg p = argparse.ArgumentParser(description=__doc__.splitlines()[0]) p.add_argument("--dsn", default="postgresql://postgres:lab@localhost:55706/postgres", help="Connection string.") p.add_argument("--json", help="Also write the results to this JSON file.") args = p.parse_args() c = psycopg.connect(args.dsn, autocommit=True) c.execute("DROP TABLE IF EXISTS orders, stores") c.execute("CREATE TABLE stores (id int PRIMARY KEY, name text)") c.execute("CREATE TABLE orders (order_id int, store_id int REFERENCES stores (id))") c.execute("INSERT INTO stores SELECT g, 's' || g FROM generate_series(1, 100) g") c.execute("INSERT INTO orders SELECT g, 1 + g % 100 FROM generate_series(1, 100000) g"); c.execute("ANALYZE orders, stores") def plan(sql): return [r[0] for r in c.execute("EXPLAIN (COSTS OFF) " + sql).fetchall()] rows = [] for label, sql in (("LEFT JOIN, nothing selected from stores", "SELECT o.order_id FROM orders o LEFT JOIN stores s ON s.id = o.store_id"), ("INNER JOIN, nothing selected from stores", "SELECT o.order_id FROM orders o JOIN stores s ON s.id = o.store_id")): pl = plan(sql); rows.append({"query": label, "stores_in_plan": "yes" if any("stores" in l for l in pl) else "no (join removed)", "plan": " / ".join(l.strip() for l in pl)}) # a constraint the engine does not enforce: drop the FK, insert an orphan, compare the inner join with the join-free answer c.execute("ALTER TABLE orders DROP CONSTRAINT orders_store_id_fkey"); c.execute("INSERT INTO orders VALUES (100001, 999)") with_join = c.execute("SELECT count(*) FROM orders o JOIN stores s ON s.id = o.store_id").fetchone()[0] no_join = c.execute("SELECT count(*) FROM orders").fetchone()[0] summary = {"with_join": with_join, "without_join": no_join, "differs": "yes" if with_join != no_join else "no"} for r in rows: print(f"{r['query']:<42} stores in the plan: {r['stores_in_plan']} [{r['plan']}]") print(f"with an orphan order and an unenforced key: inner join counts {with_join:,}, the join removed counts {no_join:,}") if args.json: with open(args.json, "w") as f: json.dump({"summary": summary, "tables": {"plans": rows}}, f)3Get the services it runs against, pinned to the versions we measured. Save it next to the script.
View the codeHide the code
join-elimination-with-and-without-an.compose.yml # PostgreSQL for the join-elimination-with-and-without-an lab. services: postgres: image: postgres:17.6 command: ["postgres", "-c", "shared_buffers=256MB", "-c", "max_parallel_workers_per_gather=0"] environment: POSTGRES_PASSWORD: lab ports: ["55706:5432"] healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 1s retries: 304Start the services, run the script with the defaults first, then change a knob from the table below and run it again. Remove the services when you are done.
Terminal docker compose -f join-elimination-with-and-without-an.compose.yml up -d --wait uv run join-elimination-with-and-without-an.py uv run join-elimination-with-and-without-an.py --help # every knob docker compose -f join-elimination-with-and-without-an.compose.yml down -v
| Knob · default | What it changes |
|---|---|
| --dsnpostgresql://postgres:lab@localhost:55706/postgres | Connection string. |
Our run
Is stores in the plan?
| Query | stores in the plan |
|---|---|
| LEFT JOIN, nothing selected from stores | no (join removed) |
| INNER JOIN, nothing selected from stores | yes |
LEFT JOIN, nothing selected from stores stores in the plan: no (join removed) [Seq Scan on orders o]
INNER JOIN, nothing selected from stores stores in the plan: yes [Hash Join / Hash Cond: (o.store_id = s.id) / -> Seq Scan on orders o / -> Hash / -> Seq Scan on stores s]
with an orphan order and an unenforced key: inner join counts 100,000, the join removed counts 100,001What we found
The LEFT JOIN was removed (no (join removed)); the inner join was kept (yes): PostgreSQL does not use foreign keys to remove inner joins. With the key dropped and one orphan order inserted, the inner join counted 100K orders and the join-free query 100K: a planner that trusted an unenforced key would have returned the second number for the first query.
Read it
Join elimination is free performance when the constraint holds and a silent wrong answer when it does not. Declaring a constraint without enforcing it is a promise the planner will act on; keep such declarations for keys you verify by some other means, and test them, because nothing in the query will tell you that a row broke the promise.
Go further
If your engine supports declared-but-unenforced constraints (for example Spark SQL with RELY, or Oracle with RELY NOVALIDATE), insert a row that violates the constraint and see that the answer changes when the join is removed.