PostgreSQL Performance Boost: Fixing a 3,000x Speedup

Changed just one word in a PostgreSQL function… and got a 3,000× speedup ⚡ Here’s what happened 👇 I had a simple UPDATE on a primary key — something that should take <1ms. Reality: ~498ms per call 9,500 calls ~80 minutes wasted 😅 After digging deeper, the culprit was surprisingly subtle: 👉 The function parameter was declared as NUMERIC 👉 The actual column type was BIGINT PostgreSQL was silently casting types on every call, which prevented the planner from reusing the optimal index plan inside PL/pgSQL. No errors. No warnings. Just a performance killer hiding in plain sight. The fix? One line: NUMERIC → BIGINT Result: Before: ~502ms/call After: 0.12ms/call 🚀 Key takeaways: 1️⃣ Enable pg_stat_statements in production, whenever required → You won’t see issues like this otherwise 2️⃣ Always match function parameter types with column types → Implicit casts are not “free” 3️⃣ Don’t rely only on EXPLAIN ANALYZE for ad-hoc queries → The planner behaves differently inside functions Sometimes, performance problems aren’t about complex queries or missing indexes… They’re about tiny mismatches with massive impact. iMocha Vishal Madan Sujit Karpe #PostgreSQL #Performance #DatabaseOptimization #BackendEngineering #TechLessons #Engineering

plpgsql_check can identify this issue https://github.com/okbob/plpgsql_check. Generally - slow queries analyze is super important when project starts and should be repeated every few months. Databases under higher load or with bigger data are pretty sensitive against same details - indexes, function's volatility, sometimes some hidden casts etc

This was very helpful as most of developers does think this small things as this doesn't throw error and at the end of day fall into additional calls and kills performance. Nicely explained

Thanks for sharing your experience! These is exact issue that we solved and have automated for customer migrating away from Oracle to PostgreSQL! Mapping of numeric with bigint in Postgres create implicit cast and eat up indexes access path ! In Postgres its critical to have right data type mapping across joins

See more comments

To view or add a comment, sign in

Explore content categories