SQL Query Optimizations (original) (raw)

Last Updated : 11 Jun, 2026

Poorly written SQL queries can make your database slow, use too many resources, cause locking problems, and give a bad experience to users. Following best practices for writing efficient SQL queries helps improve database performance and ensures optimal use of system resources.

**1. Use Indexes Wisely

Indexes help the database find data faster without scanning the whole table.

**Example: Creating an index on customer_id if there are frequent queries on this column like the following query.

SELECT * FROM orders WHERE customer_id = 123;

Creating an index on customer_id makes this query much faster:

CREATE INDEX idx_orders_customer_id ON orders(customer_id);

The above query will run much faster if customer_id is indexed.

**Indexing Guidelines

2. Avoid SELECT *: Choose Only Required Columns

Using SELECT * can make queries slow, especially on large tables or when joining multiple tables. This is because the database retrieves all columns, even the ones you don’t need. It uses more memory, takes longer to transfer data, and makes the query harder for the database to optimize.

**Avoid this:

SELECT * FROM products;

**Use this instead:

SELECT product_id, product_name, price FROM products;

**Benefits:

3. Limit Rows with WHERE and LIMIT

Fetching too many rows can make your query slow. Even if your app needs only 10 rows, the database might return thousands. Use WHERE to filter data and LIMIT to get only the rows you need.

**Example:

SELECT name FROM customers WHERE country = 'USA' ORDER BY signup_date DESCLIMIT 50;

Benefits:

4. Write Efficient WHERE Clauses

The WHERE clause filters rows in a query, but how you write it affects performance. Using functions or calculations on columns can stop the database from using indexes, which makes the query slower.

**Poor Example:

SELECT * FROM employees WHERE YEAR(joining_date) = 2022;

**Drawback: Applying YEAR() to every row stops the database from using indexes.

**Optimized Example:

SELECT * FROM employees WHERE joining_date >= '2022-01-01' AND joining_date < '2023-01-01';

Performance Tips:

5. Use Joins Smartly

Join only the tables you need and filter data before joining. Use INNER JOIN instead of OUTER JOIN if you don’t need unmatched rows.

**Example:

SELECT u.name, o.amount
FROM users u
JOIN orders o ON u.user_id = o.user_id
WHERE o.amount > 100;

Benefits:

6. Avoid N+1 Query Problems

N+1 happens when you run one query to get a list, then run extra queries for each item. Fetch related data in a single query using JOINs instead.

**Poor Approach:

SELECT * FROM users;
-- For each user: SELECT * FROM orders WHERE user_id = ?

**Recommended Approach:

SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
JOIN orders o ON u.user_id = o.user_id;

Benefits:

7. Use EXISTS Instead of IN (for Subqueries)

When you want to check whether a specific record exists in a table, using the EXISTS operator is often faster than using IN. This is particularly true when the subquery returns a large number of rows, because EXISTS stops searching as soon as it finds the first matching record, whereas IN has to process all the results before making the comparison.

**Poor Approach:

SELECT name FROM customers
WHERE customer_id IN (SELECT customer_id FROM orders);

**Recommended Approach:

SELECT name FROM customers
WHERE EXISTS (
SELECT 1 FROM orders WHERE orders.customer_id = customers.customer_id
);

Benefits:

8. Avoid Wildcards at the Start of LIKE

Don’t start a LIKE pattern with % because it disables index use and causes a full table scan.

**Poor Approach:

SELECT * FROM users WHERE name LIKE '%john';

**Recommended Approach:

SELECT * FROM users WHERE name LIKE 'john%';

Benefits:

9. Use Query Execution Plan

Check how the database runs your query using EXPLAIN (MySQL/PostgreSQL) to see slow parts.

**Example:

EXPLAIN SELECT * FROM orders WHERE user_id = 42;

Benefits:

10. Use UNION ALL Instead of UNION (if possible)

UNION removes duplicates, which adds sorting overhead. Use UNION ALL if duplicates don’t matter.

**Poor Approach:

SELECT col FROM table1
UNION
SELECT col FROM table2;

**Recommended Approach:

SELECT col FROM table1
UNION ALL
SELECT col FROM table2;

Benefits: