- Регистрация
- 1 Мар 2015
- Сообщения
- 1,481
- Баллы
- 155
10 SQL Anti-Patterns You Must Avoid in Production
As SQL developers and data engineers, we often prioritize functionality and overlook query quality. But poor SQL habits can lead to:“Slow SQL isn’t always about bad servers — it’s often about bad habits.”
- Long response times
- Bottlenecked applications
- Excessive I/O and CPU
- Poor scalability
In this post, we’ll break down 10 critical SQL anti-patterns and how to fix them.
Problem: Querying in a loop for each record.
-- BAD: Fetching orders per customer inside loop
SELECT * FROM Customers;
-- For each customer:
SELECT * FROM Orders WHERE customer_id = ?;
SELECT c.id, c.name, COUNT(o.id) AS order_count
FROM Customers c
LEFT JOIN Orders o ON o.customer_id = c.id
GROUP BY c.id, c.name;
Problem: Leading wildcard disables index usage.
SELECT * FROM Products WHERE name LIKE '%phone';
-- Better (index usable)
SELECT * FROM Products WHERE name LIKE 'phone%';
Problem: Filtering numeric column with a string.
SELECT * FROM Orders WHERE id = '123';
SELECT * FROM Orders WHERE id = 123;
? Use query plans to detect implicit conversion overhead.
Problem: Executing subquery for every row.
SELECT id, (SELECT COUNT(*) FROM OrderItems WHERE order_id = o.id)
FROM Orders o;
SELECT o.id, COUNT(oi.id) AS item_count
FROM Orders o
LEFT JOIN OrderItems oi ON oi.order_id = o.id
GROUP BY o.id;
Problem: Fetches unnecessary columns, causes bloat.
SELECT * FROM Transactions;
SELECT id, amount, transaction_date FROM Transactions;
Problem: Using DISTINCT to patch bad joins.
SELECT DISTINCT name FROM Customers c JOIN Orders o ON o.customer_id = c.id;
-- Danger zone!
DELETE FROM Users;
UPDATE Orders SET status = 'Shipped';
DELETE FROM Users WHERE is_deleted = true;
Problem: FK lookups scan entire referenced table.
-- Missing index on Orders.customer_id
CREATE INDEX idx_orders_customer ON Orders(customer_id);
SELECT * FROM Orders WHERE status = 'pending' OR status = 'shipped';
SELECT * FROM Orders WHERE status = 'pending'
UNION ALL
SELECT * FROM Orders WHERE status = 'shipped';
Problem: Blindly writing queries without measuring impact.
EXPLAIN ANALYZE SELECT ...
Final Thoughts: Write It Once, Run It Well
Avoiding anti-patterns isn't just about style — it's about performance, reliability, and cost.
#SQL #Performance #AntiPatterns #QueryOptimization #BestPractices #AdvancedSQL #DataEngineering"SQL is declarative. Let the engine help — but don’t tie its hands with bad habits."