Logo

dev-resources.site

for different kinds of informations.

🗄️ 30 Ways to Optimize Your SQL

Published at
1/7/2025
Categories
database
sql
backend
programming
Author
Leapcell
Categories
4 categories in total
database
open
sql
open
backend
open
programming
open
🗄️ 30 Ways to Optimize Your SQL

Cover

1. Choose Appropriate Indexes

Tips

Create suitable indexes (single-column, composite indexes, etc.) for columns frequently used in queries.

Example

Problematic SQL:

SELECT name FROM employees WHERE department_id = 10;

Optimization: Create an index for department_id:

CREATE INDEX idx_department_id ON employees(department_id);

2. Avoid Using SELECT *

Tips

Query only the required columns to reduce the amount of returned data.

Example

Problematic SQL:

SELECT * FROM employees WHERE department_id = 10;

Optimization: Query only necessary columns:

SELECT name FROM employees WHERE department_id = 10;

3. Prefer JOIN Over Subqueries

Tips

Subqueries are generally less efficient than JOINs.

Example

Problematic SQL:

SELECT name FROM employees WHERE department_id IN (SELECT id FROM departments WHERE location = 'New York');

Optimization: Use JOIN instead of subquery:

SELECT e.name FROM employees e JOIN departments d ON e.department_id = d.id WHERE d.location = 'New York';

4. Use EXPLAIN to Analyze Queries

Tips

Use EXPLAIN or EXPLAIN ANALYZE to view the execution plan of SQL queries and identify performance bottlenecks.

Example

EXPLAIN SELECT name FROM employees WHERE department_id = 10;

5. Avoid Unnecessary ORDER BY Operations

Tips

ORDER BY consumes significant resources, especially for large datasets. Use it only when sorting is necessary.

Example

Problematic SQL:

SELECT name FROM employees WHERE department_id = 10 ORDER BY hire_date;

Optimization: Remove ORDER BY if sorting is not needed.

6. Optimize Pagination Queries Using LIMIT

Tips

For pagination, use LIMIT. For queries with large offsets, optimize using indexes or caching.

Example

Problematic SQL:

SELECT name FROM employees ORDER BY hire_date LIMIT 100000, 10;

Optimization: Use primary keys or indexes to improve pagination performance:

SELECT name FROM employees WHERE id > 100000 ORDER BY hire_date LIMIT 10;

7. Avoid Using Functions in WHERE Clauses

Tips

Function calls prevent index usage; avoid them where possible.

Example

Problematic SQL:

SELECT name FROM employees WHERE YEAR(hire_date) = 2023;

Optimization: Use range queries instead:

SELECT name FROM employees WHERE hire_date BETWEEN '2023-01-01' AND '2023-12-31';

8. Choose Proper Order for Composite Indexes

Tips

In composite indexes, place the column with higher selectivity first.

Example

For the query:

SELECT * FROM employees WHERE department_id = 10 AND status = 'active';

Create an index with status first for better selectivity:

CREATE INDEX idx_status_department ON employees(status, department_id);

9. Use Batch Inserts Instead of Single Inserts

Tips

Batch inserts significantly reduce I/O and locking overhead.

Example

Problematic SQL: Insert records one by one:

INSERT INTO employees (name, department_id) VALUES ('John', 10);

Optimization: Use batch inserts:

INSERT INTO employees (name, department_id) VALUES ('John', 10), ('Alice', 20), ('Bob', 30);

10. Avoid Using NOT IN

Tips

NOT IN has poor performance; replace it with NOT EXISTS or LEFT JOIN.

Example

Problematic SQL:

SELECT name FROM employees WHERE department_id NOT IN (SELECT id FROM departments);

Optimization: Use LEFT JOIN:

SELECT e.name FROM employees e LEFT JOIN departments d ON e.department_id = d.id WHERE d.id IS NULL;

11. Avoid Redundant DISTINCT

Tips

Use DISTINCT only when duplicate data needs removal.

Example

Problematic SQL:

SELECT DISTINCT name FROM employees WHERE department_id = 10;

Optimization: Remove DISTINCT if duplicates are unnecessary.

12. Use Appropriate Join Types

Tips

Prefer INNER JOIN unless all data is required. Avoid LEFT JOIN or RIGHT JOIN unnecessarily.

Example

Problematic SQL:

SELECT e.name, d.name FROM employees e LEFT JOIN departments d ON e.department_id = d.id;

Optimization: Use INNER JOIN:

SELECT e.name, d.name FROM employees e INNER JOIN departments d ON e.department_id = d.id;

13. Use Table Partitioning

Tips

Partition large tables to improve query performance.

Example

CREATE TABLE employees (
    id INT,
    name VARCHAR(50),
    hire_date DATE
)
PARTITION BY RANGE (YEAR(hire_date)) (
    PARTITION p2020 VALUES LESS THAN (2021),
    PARTITION p2021 VALUES LESS THAN (2022)
);

14. Optimize GROUP BY Queries

Tips

Optimize GROUP BY queries using indexes.

Example

SELECT department_id, COUNT(*) FROM employees GROUP BY department_id;

15. Optimize IN Usage

Tips

For large IN operations, store data in temporary tables and use JOIN instead.

Example

Problematic SQL:

SELECT name FROM employees WHERE department_id IN (1, 2, 3, 4, 5);

Optimization: Store IDs in a temporary table:

CREATE TEMPORARY TABLE temp_ids (id INT);
INSERT INTO temp_ids (id) VALUES (1), (2), (3), (4), (5);
SELECT e.name FROM employees e JOIN temp_ids t ON e.department_id = t.id;

16. Limit the Use of Complex Views

Tips

Views add complexity and performance overhead. Use direct SQL for complex queries.

Example

Replace complex view queries with optimized SQL statements.

17. Optimize Lock Usage

Tips

Use appropriate locking mechanisms to avoid full-table locks (e.g., LOCK IN SHARE MODE).

Example

SELECT * FROM employees WHERE id = 10 FOR UPDATE;

18. Optimize INSERT INTO SELECT Statements

Tips

Use indexes in INSERT INTO SELECT statements to improve performance.

Example

INSERT INTO employees_backup (id, name)
SELECT id, name FROM employees WHERE hire_date < '2020-01-01';

19. Use Connection Pools

Tips

For frequent database operations, use connection pools to improve efficiency.

Example

Configure a connection pool at the application level.

20. Monitor and Adjust Memory Parameters

Tips

Adjust memory settings (e.g., MySQL’s innodb_buffer_pool_size) to match query demands.

Example

Tune configurations based on query memory requirements.

21. Optimize Distributed Queries

Tips

In distributed database environments, minimize cross-node data transfer and optimize query plans.

Example

Problematic SQL:

SELECT e.name, d.name
FROM employees e JOIN departments d
ON e.department_id = d.id
WHERE e.location = 'New York';

Optimization: Process location-related data on the local node before global aggregation to avoid cross-node data transfer.

22. Multi-Column Index and Index Merging

Tips

When querying multiple columns, use composite indexes where possible. If not, the database may attempt index merging.

Example

Problematic SQL:

SELECT * FROM orders WHERE customer_id = 10 AND product_id = 5;

Optimization: Combine indexes on customer_id and product_id for better performance. Use EXPLAIN to check if index merging is utilized.

23. Optimize Multi-Dimensional Analysis with CUBE and ROLLUP

Tips

Use CUBE and ROLLUP for multi-dimensional aggregation, reducing multiple GROUP BY queries.

Example

Problematic SQL: Multiple GROUP BY queries.

SELECT department_id, SUM(sales) FROM sales_data GROUP BY department_id;
SELECT region, SUM(sales) FROM sales_data GROUP BY region;

Optimization: Use ROLLUP to aggregate at multiple levels:

SELECT department_id, region, SUM(sales)
FROM sales_data
GROUP BY department_id, region WITH ROLLUP;

24. Use Window Functions for Complex Analysis Queries

Tips

Window functions (e.g., ROW_NUMBER(), RANK(), LAG(), LEAD()) simplify complex analysis, reducing the need for self-joins or subqueries.

Example

Problematic SQL: Self-join to fetch the previous record.

SELECT a.*,
       (SELECT sales FROM sales_data b WHERE b.id = a.id - 1) AS previous_sales
FROM sales_data a;

Optimization: Use a window function:

SELECT id, sales, LAG(sales, 1) OVER (ORDER BY id) AS previous_sales
FROM sales_data;

25. Partition Pruning for Large Tables

Tips

Use partition pruning to limit the data scan range for very large tables.

Example

Problematic SQL:

SELECT * FROM transactions WHERE transaction_date BETWEEN '2023-01-01' AND '2023-01-31';

Optimization: Partition the table by date and leverage pruning:

CREATE TABLE transactions (
    id INT,
    amount DECIMAL(10, 2),
    transaction_date DATE
)
PARTITION BY RANGE (YEAR(transaction_date)) (
    PARTITION p2023 VALUES LESS THAN (2024)
);

26. Minimize Temporary Table Usage

Tips

Reduce temporary table usage in complex queries as they increase disk I/O and impact performance.

Example

Problematic SQL: Using a temporary table to store intermediate results.

CREATE TEMPORARY TABLE temp_sales AS
SELECT department_id, SUM(sales) FROM sales_data GROUP BY department_id;

Optimization: Use subqueries or Common Table Expressions (CTEs):

WITH temp_sales AS (
    SELECT department_id, SUM(sales) FROM sales_data GROUP BY department_id
)
SELECT * FROM temp_sales;

27. Optimize Parallel Queries

Tips

Leverage parallel query execution for large datasets to improve efficiency.

Example

Problematic SQL: A large data scan without parallelism.

SELECT SUM(sales) FROM sales_data;

Optimization: Enable parallel query execution:

ALTER SESSION ENABLE PARALLEL QUERY;
SELECT /*+ PARALLEL(sales_data, 4) */ SUM(sales) FROM sales_data;

28. Accelerate Complex Queries with Materialized Views

Tips

For complex aggregation queries, use materialized views to store precomputed results.

Example

Problematic SQL: Complex aggregation query with performance bottlenecks.

SELECT department_id, SUM(sales) FROM sales_data GROUP BY department_id;

Optimization: Create a materialized view:

CREATE MATERIALIZED VIEW mv_sales_data AS
SELECT department_id, SUM(sales) AS total_sales FROM sales_data GROUP BY department_id;

29. Avoid Lock Contention to Optimize Concurrent Queries

Tips

In high-concurrency environments, avoid table or row locks by using appropriate locking mechanisms.

Example

Problematic SQL: Table lock causing performance degradation under high concurrency.

SELECT * FROM orders WHERE status = 'pending' FOR UPDATE;

Optimization: Lock only specific rows:

SELECT * FROM orders WHERE order_id = 123 FOR UPDATE;

30. Optimize Transactions by Reducing Locking Time

Tips

For long-running transactions, minimize locking time and reduce the scope of locks.

Example

Problematic SQL: Large-scale data operations locking tables during the transaction.

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;

Optimization: Split into smaller transactions or reduce lock time:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
COMMIT;

BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;

Optimizing SQL queries is both an art and a science.

The techniques outlined above provide a robust foundation for improving query performance, but the key to true mastery lies in constant experimentation and adaptation.

Every database is unique - what works for one scenario may not work for another. Always analyze, test, and refine your queries to build your own optimization.

We are Leapcell, your top choice for deploying backend projects to the cloud.

Leapcell

Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:

Multi-Language Support

  • Develop with Node.js, Python, Go, or Rust.

Deploy unlimited projects for free

  • pay only for usage — no requests, no charges.

Unbeatable Cost Efficiency

  • Pay-as-you-go with no idle charges.
  • Example: $25 supports 6.94M requests at a 60ms average response time.

Streamlined Developer Experience

  • Intuitive UI for effortless setup.
  • Fully automated CI/CD pipelines and GitOps integration.
  • Real-time metrics and logging for actionable insights.

Effortless Scalability and High Performance

  • Auto-scaling to handle high concurrency with ease.
  • Zero operational overhead — just focus on building.

Explore more in the Documentation!

Try Leapcell

Follow us on X: @LeapcellHQ

Read on our blog

Featured ones: