🚧 SQL Server → PostgreSQL Migration: 2 Critical Challenges I Solved During migration, the toughest part was handling stored procedures behavior differences while ensuring zero backend changes. 🔴 Challenge 1: IN/OUT Parameters SQL Server: · OUT parameters are optional · Procedures return values without strict definition -- SQL Server CREATE PROCEDURE GetData @Id INT AS BEGIN SELECT * FROM Table1 WHERE Id = @Id END PostgreSQL: · OUT parameters must be defined · Execution pattern differs 🔴 Challenge 2: Multiple Result Sets SQL Server: · One procedure → multiple result sets SELECT * FROM ClientMaster; SELECT * FROM BankMaster; Backend consumes both outputs directly. PostgreSQL: · Cannot return multiple result sets directly ⚡ Combined Solution ✔ Converted Stored Procedures → PostgreSQL Functions ✔ Used **JSON/JSONB** to handle: · Multiple result sets · Output structure -- PostgreSQL (Concept) SELECT jsonb_build_object( 'clients', (SELECT json_agg(c) FROM client_master c), 'banks', (SELECT json_agg(b) FROM bank_master b) ); ✔ Maintained: · Same business logic · Same execution behavior · No backend code changes 🧠 Approach SQL Server Behavior ↓ Analyze Output Pattern ↓ Design Compatible Structure (JSON) ↓ Implement in PostgreSQL Function ↓ Validate with Backend 📊 Result ✅ Multiple datasets handled in single response ✅ No backend impact ✅ Clean and scalable approach 💡 Key Learning: When migrating across databases, feature parity is not guaranteed — designing the right abstraction (like JSON) is the real solution. #PostgreSQL #SQLServer #DatabaseMigration #JSON #DataEngineering #SQL
SQL Server to PostgreSQL Migration: Handling Stored Procedures and Multiple Result Sets
More Relevant Posts
-
🐘 Say Goodbye to Migration Headaches with pgloader If you’ve ever had to migrate a database to PostgreSQL, you know the "schema vs. data" struggle. Most tools make you export the schema first, fix it, then import data separately. Enter pgloader—a powerful, open-source tool that automates the entire "Continuous Migration" process in a single command. 🛠️ What can pgloader transform? It doesn't just copy data; it intelligently transforms different source structures into a clean PostgreSQL structure. Supported sources include: ✅ Databases: MySQL, MS SQL Server, SQLite, and Redshift. ✅ Files: CSV, Fixed-format files, dBase (DBF), and IBM IXF. ✅ On-the-fly Transformation: It automatically handles type casting (like converting MySQL's 0000-00-00 dates to NULL) and re-indexes your tables. ⚙️ Flexibilty: Schema vs. Data One of the best features is how it handles different migration needs: SCHEMA ONLY: Use the CREATE NO DATA clause if you only want to replicate the structure. DATA ONLY: Use the CREATE NO SCHEMA clause if you’ve already prepared your target tables (popular for ORM-heavy projects). FULL MIGRATION: By default, it creates the schema, loads the data, and resets sequences—all in one go. 💡 Why I like it It’s built for speed. By using the PostgreSQL COPY protocol and parallel workers, it’s significantly faster than standard INSERT scripts. Plus, it generates a "Summary Report" at the end so you know exactly how many rows were moved and if any errors occurred. Are you a GUI person (like AWS SCT) or a CLI person (like pgloader)? Let’s discuss in the comments! #PostgreSQL #DatabaseMigration #OpenSource #SQL #DataEngineering #pgloader #BackendDevelopment
To view or add a comment, sign in
-
🚀 PostgreSQL Query Optimization Explained (For Developers) Writing a query is easy… Writing a fast query is what makes you a strong developer 👇 ⚡ What is Query Optimization? It’s the process of improving your SQL queries so they run faster and use fewer resources. 🧠 Why It Matters? - Faster APIs 🚀 - Better user experience - Lower database load - Scales better in production 🛠️ Key Techniques to Learn: 🔍 EXPLAIN / ANALYZE Understand how PostgreSQL executes your query and identify bottlenecks 📌 Indexing Add indexes on frequently queried columns (especially WHERE, JOIN) 🚫 Avoid SELECT * Fetch only required columns to reduce data load 🔄 Optimize Joins Use proper joins and ensure join columns are indexed 📦 Limit & Pagination Use LIMIT/OFFSET or cursor-based pagination for large datasets 🧩 Query Refactoring Break complex queries into simpler parts when needed 🔥 Real Use Case: Slow API fetching users → optimize with indexing + proper query → response time drops from seconds to milliseconds ⚠️ Common Mistake: Ignoring slow queries until production issues happen ❌ 💡 Pro Tip: Always test queries with realistic data size — performance issues often appear only at scale #PostgreSQL #SQL #Database #Performance #BackendDeveloper #SystemDesign #LearnToCode
To view or add a comment, sign in
-
-
Most developers add database indexes expecting instant magic speed… …but many accidentally slow down their entire system instead. Here’s exactly how database indexing works under the hood — and why it’s a double-edged sword: Indexes are separate data structures that store a sorted map of your column values and point directly to the actual rows in the table. Instead of scanning every single row (a slow full table scan), the database can quickly jump to the right data — often in just a few steps. The Major Advantages: Lightning-fast reads: B-Tree indexes (the default in most databases) give O(log n) search time. They efficiently handle equality (=), range queries (>, <, BETWEEN), sorting, and JOINs. Specialized indexes unlock extra power: Hash indexes deliver true O(1) speed for exact matches, Bitmap indexes excel with low-cardinality data in analytics, and GiST/GIN handle full-text or spatial searches beautifully. Result: Queries that dragged for seconds now return in milliseconds, even on million-row tables. The Real Trade-Offs (Where It Hurts): Extra storage cost: Indexes can easily double or triple the size of your table. Slower writes: Every INSERT, UPDATE, or DELETE has to update all related indexes. This adds significant overhead and disk I/O, especially on high-write workloads. Maintenance burden: Choosing the wrong index type (like Hash for range queries) or creating too many indexes wastes space and can actually hurt performance. The smart approach: Focus indexes on columns frequently used in WHERE, ORDER BY, or JOIN conditions — especially on read-heavy tables. Regularly check which indexes are actually being used and drop the unused ones. Test changes carefully. Mastering this trade-off is what turns good backend systems into highly scalable ones. What’s your biggest indexing win — or the hardest lesson you learned about indexes? Drop it in the comments 👇 I read every single one. #DatabaseEngineering #SQL #PerformanceOptimization #BackendDevelopment #PostgreSQL #MySQL #DataEngineering #SystemDesign
To view or add a comment, sign in
-
-
Is your query actually slow, or just long-running? This distinction is often misunderstood but critical for effective tuning. In my recent blog I have explained how to identify and analyze query behavior correctly - https://lnkd.in/d4y_JJP4 Would love your thoughts and experiences! #PostgreSQL #PerformanceTuning #DBA #SQL #TechBlog #Opensource
To view or add a comment, sign in
-
I got depressed a bit reading this article. I realized that I remember SQL before we had CTEs and I remember when they first appeared. Around 2005-2010-ish on engines I was using at that time. I remember it clearly. We all used temporary tables, there were no CTEs. And when they came, they were lame because they couldn't replace our beloved temp tables on SQL Server. Why? Because by just having a CTE on top of your query doesn't forces execution order. Optimizer sees them and pushes them into the main query like they are some lame subquery. And all we wanted was specific order enforced and results reused, but no, not with CTE you don't, and so we kept with temp tables as we were. As this article explains, PostgreSQL was different (when they first implemented). Prior to version 12, CTEs would always execute first, results would materialize (disk, memory, doesn't matter, it's all abstracted) and be ready to be reused. But after version 12, PostgreSQL behaves as SQL Server, it just takes your CTE and pushes it down into the main query like it was some subquery or something. Good for optimization. Not so much for enforcing execution order and having materialized results that can be reused multiple times (which is also optimization when you think about it). That's why PostgreSQL has this MATERIALIZED keyword to enforces thus behavior explicitly. And it's arguably the most advanced CTE support in the world. Maybe with, I don't know, Oracle, maybe. Oracle has rhat too (had to ask my AI little helper). Boring SQL article: https://lnkd.in/d-t8sH84
To view or add a comment, sign in
-
Did adding just ONE line of code make your database query 100x faster? 🤔⚡ ------------------------------- We’ve all seen it happen. An application is crawling, a specific query is taking 3 seconds, and the user experience suffers. You add an index, and suddenly it takes 0.03 seconds. It feels like magic. But it’s actually fundamental data structure engineering. Here is what really happens when you index a database like PostgreSQL or MySQL: ❌ The Problem: The Full Table Scan Imagine I hand you a 1,000-page biology textbook and ask you to find every mention of the word "mitochondria." Without a glossary, you have to read every single page, start to finish. This is a Full Table Scan. It is mathematically predictable, but slow. If the table (the book) grows from 1,000 pages to 10 million pages, your query becomes unusable. ✅ The Solution: Database Indexing An index is a sorted glossary of specific data points (like user IDs or emails). Behind the scenes, the database builds a specialized data structure, usually a B-Tree or a Hash Map. Instead of reading 10 million rows, the database uses the B-Tree's sorted architecture to find your data packet in milliseconds. It doesn’t work harder; it just knows exactly where to look. ⚖️ The Trade-off (Crucial Point!) Indexes are powerful, but they aren't free: Storage Costs: Indexes take up extra disk space. A heavy index on a massive table can significantly increase storage needs. Slower Write Operations: Every time you INSERT a new row, the database also has to spend time updating the index (glossary). Writing too many indexes can slow down your data writes. ------------------------------- Conclusion: Database speed isn't about hope. It's about knowing your access patterns and building the right B-Trees. 🚀 #Database #SoftwareEngineering #PostgreSQL #MySQL #BackendDevelopment #TechTips #PerformanceEngineering
To view or add a comment, sign in
-
-
🚀 Important PostgreSQL Concepts Every Developer Should Learn If you're working with PostgreSQL, just knowing basic queries isn’t enough. To become a strong backend developer, you need to understand these core concepts 👇 🧠 1️⃣ Indexing Speeds up your queries drastically. Learn B-Tree, Hash indexes, and when to use them. 🔗 2️⃣ Joins Master INNER, LEFT, RIGHT joins to combine data across tables efficiently. ⚡ 3️⃣ Query Optimization Understand EXPLAIN / ANALYZE to debug slow queries and improve performance. 🔄 4️⃣ Transactions & ACID Learn how PostgreSQL ensures data consistency using transactions (COMMIT, ROLLBACK). 📦 5️⃣ Normalization Design clean and efficient schemas by avoiding data redundancy. 🔐 6️⃣ Locks & Concurrency Understand how PostgreSQL handles multiple users accessing data at the same time. 🧾 7️⃣ Views & Materialized Views Simplify complex queries and improve performance for repeated reads. ⚙️ 8️⃣ Stored Procedures & Functions Move business logic closer to the database for efficiency. 📊 9️⃣ Partitioning Handle large datasets by splitting tables for better performance. 🔁 🔟 Replication Learn read replicas & high availability for production systems. 🔥 Real Insight: Most developers stop at CRUD — but real growth happens when you understand how the database works internally. #PostgreSQL #Database #BackendDeveloper #SystemDesign #SQL #SoftwareEngineering #LearnToCode
To view or add a comment, sign in
-
-
I thought JOIN order in SQL is fixed based on how we write the query. Turns out… PostgreSQL doesn’t really care. Tried analyzing how a 3-table JOIN executes in PostgreSQL on ~200k rows. Not just the result — but the execution plan behind it. Here’s what I observed 👇 1️⃣ Basic 3-table JOIN SELECT u.id, o.amount, p.status FROM users u JOIN orders o ON u.id = o.user_id JOIN payments p ON o.id = p.order_id; 🔸 Expected execution: (users JOIN orders) → then JOIN payments 🔸 Actual Execution Plan: (orders JOIN payments) → then JOIN users ⏱ Execution time: ~1s 🪴 Observation: PostgreSQL didn’t follow the query order. It reordered joins based on cost. 2️⃣ Adding a filter on payments WHERE p.status = 'success'; 🔸 Execution Plan: Still (orders JOIN payments) first ⏱ Execution time: ~700 ms 🪴 Observation: The filter reduced rows early (~200k → ~140k), so PostgreSQL chose the join order that minimises intermediate data. 3️⃣ Looking deeper into execution 🔸 Join Type: Merge Join 🔸 Sorting: External merge (disk) 🪴 Observation: Even with indexes, sorting spilled to disk — which added extra cost. 4️⃣ What this revealed about JOIN behavior 🪴 Observation: • JOIN order is not fixed — PostgreSQL decides it • It tries to reduce intermediate result size early • Join order often matters more than join type • Even optimized plans can have hidden costs like disk sorting 💡 What I found interesting is that PostgreSQL is constantly balancing trade-offs: • Reducing rows early • Choosing join strategies • Managing memory vs disk operations Same query. Same tables. Different execution strategies. Exploring execution plans made me realize that writing SQL is only part of the story — understanding how the database executes it is where things get interesting. Curious to hear from others working with databases — have you ever seen PostgreSQL pick an unexpected JOIN order? #PostgreSQL #DatabaseInternals #SQL #QueryOptimization
To view or add a comment, sign in
-
-
⚡ Indexing Strategy I Used After SQL Server → PostgreSQL Migration After migration, one major improvement area I worked on was index optimization in PostgreSQL. Because even a perfectly migrated database can perform poorly without the right indexing strategy. 🔴 Problem Post-migration observations: Some queries became slower Existing indexes from SQL Server were not fully effective Different query planner behavior in PostgreSQL ⚡ Approach I Followed ✔ Analyzed frequently used queries Focused on WHERE, JOIN, ORDER BY columns ✔ Validated existing indexes Removed unused / redundant indexes ✔ Created optimized indexes Single-column indexes for filters Multi-column indexes for joins ✔ Used PostgreSQL-specific features Partial indexes (for filtered data) Index-only scans (where possible) ✔ Balanced indexing Avoided over-indexing (write performance impact) 🔄 Index Optimization Flow Identify Slow Queries ↓ Analyze Execution Plan ↓ Check Existing Indexes ↓ Create / Modify Index ↓ Test Performance ↓ Deploy 📊 Result ✅ Faster query execution ✅ Reduced load on database ✅ Improved overall performance 💡 Key Learning: Indexes should be designed based on query patterns, not blindly migrated from source systems. #PostgreSQL #Indexing #PerformanceTuning #SQLServer #DataEngineering #SQL
To view or add a comment, sign in
-
-
Last week I wrote about how more teams are talking about moving from SQL Server to PostgreSQL. Since then, I’ve had a bunch of messages and sales calls basically saying the same thing: “Licensing is killing us. Should we just switch to Postgres?” I get it. SQL Server licensing is expensive and Postgres is “free.” But “free” isn’t free. I cannot say this often enough! It just moves the cost into places people don’t budget for, and it’s why cross-platform database migrations go sideways more often than expected. Here’s what gets underestimated (almost every time): 1) 𝐂𝐨𝐦𝐩𝐚𝐭𝐢𝐛𝐢𝐥𝐢𝐭𝐲 𝐝𝐞𝐛𝐭 Data types don’t map cleanly. Collation/encoding surprises. Edge cases that only show up under real workloads. Stored procedures rewritten. T-SQL doesn’t translate 1:1 to Postgres syntax or procedural logic. 2) 𝐀𝐩𝐩𝐥𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐝𝐞𝐩𝐞𝐧𝐝𝐞𝐧𝐜𝐢𝐞𝐬 Connection strings are the easy part. Query behavior differences, transaction semantics, error handling, and driver quirks show up later... usually in production. 3) 𝐓𝐞𝐚𝐦 𝐞𝐱𝐩𝐞𝐫𝐭𝐢𝐬𝐞 Your team knows SQL Server under pressure. Postgres is a different product with different tooling, monitoring, and failure modes. The learning curve is real. 4) 𝐓𝐨𝐭𝐚𝐥 𝐜𝐨𝐬𝐭 𝐨𝐟 𝐨𝐰𝐧𝐞𝐫𝐬𝐡𝐢𝐩 Yes, the license is free. But you still pay for expertise, retraining, rebuilding monitoring, regression testing, and closing feature gaps with tooling or services. I’m not anti-Postgres. It’s a great database. I’m anti “we’ll save money” migrations that turn into multi-quarter projects and don’t come out clearly ahead on total cost for years. If licensing is the driver, there’s often a better path before you change platforms: • Right-size your SQL Server estate • Move Enterprise → Standard where you qualify • Reduce core count through performance tuning • Consolidate instances where it makes sense Sometimes the cheapest migration is the one you don’t do.
To view or add a comment, sign in
Explore related topics
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development