All insightsInsights · 5 min read

How to Clean Up a Bloated WooCommerce and Elementor Database

A step-by-step guide to removing orphaned WooCommerce data, trimming Elementor revisions safely and adding Redis or Memcached object caching for faster checkouts.

A bloated WordPress database slows down every request that cannot be served from page cache, and on a WooCommerce store that means the cart, checkout and account pages. Slower database queries increase server response time, which delays Largest Contentful Paint and drags down your Core Web Vitals.

This tutorial walks through the three cleanups that make the biggest difference on WooCommerce and Elementor sites: orphaned WooCommerce metadata, Elementor revisions, and a persistent object cache for dynamic requests.

Before you start

  • Take a full database backup and confirm you can restore it. With WP-CLI: wp db export backup-before-cleanup.sql.
  • Work on a staging copy first, then repeat on production during a quiet period.
  • Check your table prefix. The queries below use the default wp_. Replace it with the prefix in your wp-config.php.
  • Measure first. Note your checkout page’s server response time (Time to First Byte) in your browser’s developer tools, or install Query Monitor to see query counts and timings. You will compare against these numbers at the end.

To see which tables are taking up the most space, run:

SELECT table_name,
       ROUND((data_length + index_length) / 1024 / 1024, 1) AS size_mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY size_mb DESC
LIMIT 15;

Step 1: Clean up orphaned WooCommerce metadata

Orphaned metadata is data left behind after the thing it belonged to was deleted: post meta without a post, order item meta without an order item, and expired temporary data that never got removed. It adds rows to tables WooCommerce queries constantly.

1.1 Check your order storage mode

Go to WooCommerce › Settings › Advanced › Features. Since WooCommerce 8.2, new stores use High-Performance Order Storage (HPOS) by default, which keeps orders in dedicated wp_wc_orders tables instead of posts and post meta. If compatibility mode (sync) is enabled, order data is also copied to the old tables. Do not delete order data from the legacy tables while sync is on.

1.2 Remove orphaned post meta

Count the rows first, then delete them:

SELECT COUNT(*) FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

1.3 Remove orphaned order item meta

SELECT COUNT(*) FROM wp_woocommerce_order_itemmeta oim
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_id = oim.order_item_id
WHERE oi.order_item_id IS NULL;

DELETE oim FROM wp_woocommerce_order_itemmeta oim
LEFT JOIN wp_woocommerce_order_items oi ON oi.order_item_id = oim.order_item_id
WHERE oi.order_item_id IS NULL;

1.4 Delete expired transients

wp transient delete --expired

1.5 Trim the Action Scheduler log

WooCommerce uses Action Scheduler for background jobs, and by default it keeps completed and cancelled actions for 30 days. On busy stores those tables grow large. Check them under Tools › Scheduled Actions, or count by status:

SELECT status, COUNT(*) FROM wp_actionscheduler_actions
GROUP BY status;

To keep only one week of history, add this filter in a code snippet or a small plugin:

add_filter( 'action_scheduler_retention_period', function () {
	return WEEK_IN_SECONDS;
} );

1.6 Check autoloaded options

Autoloaded options are loaded on every single request. Since WordPress 6.6, Site Health warns you when they exceed 800 KB. Check the total and the largest entries:

SELECT ROUND(SUM(LENGTH(option_value)) / 1024) AS autoload_kb
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto');

SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;

Large entries often belong to plugins you removed long ago. Delete those, or switch autoloading off for options that are only needed occasionally. Recent WP-CLI versions can do this with wp option set-autoload option_name off.

1.7 Optimise the tables

wp db optimize

Step 2: Reduce Elementor post revisions safely

Every time you update an Elementor page, WordPress saves a revision, and each revision stores its own full copy of the page’s Elementor data in post meta. When I checked my own site, the home page alone had more than 900 revisions. Multiply that across a site and the post meta table grows quickly.

2.1 Count your revisions

wp post list --post_type=revision --post_status=inherit --format=count

2.2 Limit revisions going forward

Add this line to wp-config.php, above the “That’s all, stop editing” comment. It keeps the five most recent revisions per page from now on, but does not delete existing ones:

define( 'WP_POST_REVISIONS', 5 );

2.3 Delete old revisions, keeping the latest few

Always delete revisions through WordPress, using WP-CLI or a trusted optimisation plugin, not with raw SQL. WordPress then removes each revision’s post meta too. Deleting rows directly from wp_posts leaves the Elementor data behind as orphaned meta.

This command deletes all but the five newest revisions of the page with ID 123:

wp post delete $(wp post list --post_type=revision --post_status=inherit \
  --post_parent=123 --orderby=date --order=DESC \
  --offset=5 --posts_per_page=500 --format=ids) --force

Keep a fuller history on pages that are still being actively edited, so you can roll back if a client needs an earlier version.

2.4 Regenerate Elementor files

Go to Elementor › Tools and use Clear Files & Data (called Regenerate CSS & Data in older versions), then purge your page cache and check your key pages.

Step 3: Use object caching (Redis or Memcached) for dynamic requests

Page caching cannot help the cart, checkout or account pages, because WooCommerce marks them as uncacheable, and the same goes for logged-in customers and AJAX requests. Each of these runs PHP and queries the database.

WordPress has a built-in object cache, but by default it only lasts for a single request. A persistent object cache stores the results of repeated database queries in memory with Redis or Memcached, so the next request can skip MySQL entirely. Since WordPress 6.1, Site Health recommends one for larger sites.

3.1 Confirm the server supports it

You need a running Redis or Memcached service and the matching PHP extension. Many managed hosts offer one of them. On your own VPS, Redis is usually a short install, for example on Ubuntu:

sudo apt install redis-server php-redis
sudo systemctl restart php8.3-fpm   # match your PHP version

3.2 Connect WordPress to the cache

  • LiteSpeed Cache: go to LiteSpeed Cache › Cache › Object, choose Redis or Memcached, enter the host and port (Redis usually runs on 127.0.0.1, port 6379) and save.
  • Redis Object Cache plugin: install it, then go to Settings › Redis and click Enable Object Cache, or run wp redis enable.

3.3 Set a unique cache key

If more than one site shares the same Redis or Memcached server, give each site its own prefix in wp-config.php so their data never mixes:

define( 'WP_CACHE_KEY_SALT', 'mystore_' );

3.4 Verify and test

  • Check that the plugin shows the cache as connected, and that the Site Health object cache recommendation has cleared.
  • With Redis, run redis-cli info stats and confirm keyspace_hits keeps rising as you browse the store.
  • Place a test order, apply a coupon, log in and out, and check that stock levels update correctly.
  • If Redis runs on a small server, cap its memory and use maxmemory-policy allkeys-lru so old keys are evicted instead of the cache filling up.

Object caching does not fix slow queries from badly written plugins, but it removes a large amount of repeated work from every dynamic request.

Measure the result

Repeat the measurements from the start: checkout server response time, query counts in Query Monitor, and the table sizes query. Then keep the database lean by running Step 1 every few months.

Need an expert to speed up your store?

Need an expert to speed up your store? Contact me. I’ll review your database, caching and server setup and tell you exactly where the time is going.

Picture of Syed Bilawal Bukhari

Syed Bilawal Bukhari

WordPress and Elementor specialist. I build, fix and speed up WordPress sites for businesses and agencies, and I teach web development online.

More insights
Next step

Rather have it done for you?

I build, fix and speed up WordPress sites for businesses and agencies. Tell me what’s going on with yours.