When a website feels slow, the database is the usual suspect. A default MySQL or MariaDB install ships with conservative settings designed to start on almost any machine — not to perform well on yours. With a handful of targeted changes to my.cnf, the right indexes, and the slow query log to guide you, you can often cut page-load times dramatically without upgrading hardware. This guide covers practical tuning for both shared hosting and VPS environments.
First, Measure — Don’t Guess
Before changing anything, find out what your database is actually doing. The slow query log is the single most useful tuning tool:
# my.cnf — log queries slower than 1 second
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
After a day of real traffic, summarise it with mysqldumpslow (or Percona’s pt-query-digest) to see which queries cost the most total time. Fixing the top three usually wins more than any config tweak.
The Settings That Matter Most
For any InnoDB-based workload (which is nearly all WordPress, Magento, and modern apps), these are the high-impact knobs:
| Setting | What it controls | Suggested value |
|---|---|---|
innodb_buffer_pool_size | RAM used to cache data + indexes | 50–70% of total RAM (VPS) |
innodb_log_file_size | Write/commit performance | 256M–512M |
innodb_flush_log_at_trx_commit | Durability vs speed | 2 (faster) / 1 (safest) |
max_connections | Concurrent client limit | Match real concurrency, not 1000s |
tmp_table_size / max_heap_table_size | In-memory temp tables | 64M each |
The InnoDB buffer pool is the big one. If it can hold your entire working dataset in RAM, most reads never touch the disk. On a 4 GB VPS, innodb_buffer_pool_size = 2G is a sensible start.
A Sample VPS Configuration
# Example for a 4 GB RAM VPS running WordPress/WooCommerce
[mysqld]
innodb_buffer_pool_size = 2G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_connections = 100
tmp_table_size = 64M
max_heap_table_size = 64M
table_open_cache = 2000
On shared hosting you usually can’t edit my.cnf. Focus instead on what you can control: efficient queries, good indexes, and an application-level object cache like Redis or Memcached if your host offers it.
Indexing: The Biggest Free Win
A missing index turns a fast lookup into a full-table scan. Use EXPLAIN to see how the optimiser runs a query — type: ALL means a full scan, which is what you want to eliminate:
EXPLAIN SELECT * FROM orders WHERE customer_id = 42 AND status = 'paid';
-- Add an index covering the WHERE columns
CREATE INDEX idx_customer_status ON orders (customer_id, status);
Index the columns you filter, join, and sort on — but don’t over-index. Every index speeds up reads while slightly slowing writes and consuming space, so index for your real query patterns, not “just in case.”
Housekeeping
- Run
OPTIMIZE TABLEon tables with heavy delete/update churn to reclaim space and defragment. - Avoid
SELECT *— fetch only the columns you need. - Keep MySQL/MariaDB updated; newer versions have a smarter optimiser and better defaults.
- Use a tuning script like
mysqltuner.plfor a sanity check — but apply its advice with judgement, not blindly.
Conclusion
Database tuning is a loop: measure with the slow query log, fix the worst queries with indexes, size the InnoDB buffer pool to your RAM, then measure again. On a VPS, those three steps routinely deliver the biggest speed gains of any optimisation you can make — and on shared hosting, smart queries and good indexes get you most of the way there for free.
