A WordPress database grows quietly and is rarely looked at. Three things account for most of the bloat.
Post revisions
WordPress keeps a copy of every draft of every post for ever. A page edited fifty times is fifty-one rows. Useful, but not without limit. You can cap it in wp-config.php:
define( 'WP_POST_REVISIONS', 5 );
Set it to a number rather than false – turning revisions off entirely removes a genuinely useful safety net.
Transients
Temporary cached values with an expiry. WordPress is supposed to clear them and frequently does not, so expired transients accumulate in wp_options indefinitely. They are safe to delete; anything still needed is regenerated.
Autoloaded options – the important one
Rows in wp_options marked to autoload are read into memory on every single request, including every admin page and every AJAX call. That is fine at a few hundred kilobytes. Some plugins store large amounts of data as autoloaded options, and we have seen this reach several megabytes – being read, in full, thousands of times a day.
This is one of the most effective and least known performance fixes available. You can check the total in phpMyAdmin with:
SELECT SUM(LENGTH(option_value)) FROM wp_options WHERE autoload = 'yes';
If that is over about a megabyte, look at what the largest entries belong to. Often they are left behind by a plugin removed months ago.
Before you clean anything
Take a database backup. Optimisation plugins do this work for you, but they are deleting rows from your live database and an undo is exactly what a backup is.