10 MySQL Performance Optimization Techniques Every PHP Developer Must Know

php dev.to

Slow MySQL queries can cripple your web application. This guide covers indexing, query optimization, table design, and caching techniques to make your database run 10x faster.
10 MySQL Performance Optimization Techniques Every PHP Developer Must Know

A slow database query can make your entire PHP application feel sluggish. Even a 500ms query running 100 times per page load adds 50 seconds of wait time. I've compiled the 10 most effective MySQL optimization techniques that have helped me speed up real projects.

  1. Use Indexes Properly Indexes are the single most important optimization. Add indexes to columns used in WHERE, JOIN, and ORDER BY:
-- Check existing indexes
SHOW INDEX FROM users;

-- Add index to frequently searched column
ALTER TABLE users ADD INDEX idx_email (email);

-- Composite index for multiple columns
ALTER TABLE orders ADD INDEX idx_user_date (user_id, created_at);
Enter fullscreen mode Exit fullscreen mode
  1. EXPLAIN Your Queries Always use EXPLAIN to understand how MySQL executes your query:
EXPLAIN SELECT * FROM orders WHERE user_id = 5 AND status = 'pending';
Enter fullscreen mode Exit fullscreen mode

Look for:
type=ALL → full table scan (BAD)
type=ref or type=range → index used (GOOD)

  1. Select Only What You Need
// BAD - fetches all columns
$users = $db->query("SELECT * FROM users WHERE active = 1")->fetchAll();

// GOOD - fetch only needed columns
$users = $db->query("SELECT id, name, email FROM users WHERE active = 1")->fetchAll();
Enter fullscreen mode Exit fullscreen mode
  1. Solve the N+1 Query Problem
// BAD: N+1 queries
$users = $db->query("SELECT * FROM users")->fetchAll();
foreach ($users as $user) {
    $posts = $db->query("SELECT * FROM posts WHERE user_id = {$user['id']}")->fetchAll();
}

// GOOD: Single JOIN query
$results = $db->query("
    SELECT u.id, u.name, p.title
    FROM users u
    LEFT JOIN posts p ON p.user_id = u.id
")->fetchAll();
Enter fullscreen mode Exit fullscreen mode
  1. Always Paginate Large Results
-- Page 1 (20 results)
SELECT * FROM products
WHERE category_id = 5
ORDER BY created_at DESC
LIMIT 20 OFFSET 0;

-- For very large tables, use cursor pagination
SELECT * FROM products
WHERE id > :last_id
ORDER BY id ASC
LIMIT 20;
Enter fullscreen mode Exit fullscreen mode
  1. Avoid Functions on Indexed Columns
-- BAD: function prevents index usage
SELECT * FROM orders WHERE YEAR(created_at) = 2026;

-- GOOD: range query uses index
SELECT * FROM orders
WHERE created_at >= '2026-01-01'
AND created_at < '2027-01-01';
Enter fullscreen mode Exit fullscreen mode
  1. Use Proper Data Types
CREATE TABLE products (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  price DECIMAL(10,2) NOT NULL,   -- not FLOAT for money
  is_active TINYINT(1) DEFAULT 1, -- not VARCHAR for booleans
  description TEXT                 -- only TEXT when needed
);
Enter fullscreen mode Exit fullscreen mode
  1. Optimize JOINs
-- Ensure JOIN columns are indexed
ALTER TABLE orders ADD INDEX idx_customer_id (customer_id);

-- Prefer INNER JOIN over LEFT JOIN when possible
SELECT o.id, c.name
FROM orders o
INNER JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'pending';
Enter fullscreen mode Exit fullscreen mode
  1. Cache Query Results in PHP
function getCachedQuery($db, $key, $sql, $params = [], $ttl = 300) {
    $cacheFile = sys_get_temp_dir() . '/db_' . md5($key) . '.cache';

    if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $ttl) {
        return unserialize(file_get_contents($cacheFile));
    }

    $stmt = $db->prepare($sql);
    $stmt->execute($params);
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

    file_put_contents($cacheFile, serialize($result));
    return $result;
}
Enter fullscreen mode Exit fullscreen mode
  1. Monitor Slow Queries
-- Enable slow query log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Enter fullscreen mode Exit fullscreen mode

Quick Checklist
[ ] Add indexes to WHERE, JOIN, ORDER BY columns
[ ] Run EXPLAIN on slow queries
[ ] Replace SELECT * with specific columns
[ ] Fix N+1 queries with JOINs
[ ] Add LIMIT to all queries
[ ] Use range queries instead of functions on indexed columns
[ ] Use correct data types
[ ] Cache repeated queries

[ ] Monitor slow query log

I've also published detailed guides on Web Security, REST API with PHP, CSS Flexbox, and JavaScript Async/Await on my dev tools site.
Check out the free SQL Formatter tool at tsmtools.in/devtools.html — useful for cleaning up complex queries before running them.
What's your biggest MySQL performance challenge? Drop a comment below! 👇

Source: dev.to

arrow_back Back to Tutorials