Services built by a real sysadmin.

Every product in this shop was tested in production, optimized under pressure, and designed to make your infrastructure safer, faster, and cleaner.

Browse services

Fixing Slow WordPress Database Queries: Missing object_id Index in wp_term_relationships

If you’re noticing high MySQL/MariaDB load, slow queries, or “Sending data” processes when running WordPress, especially on WooCommerce or sites with many posts/products, you might be hitting this problem.


Common Symptoms

When you run SHOW PROCESSLIST;, you might see dozens or hundreds of queries stuck like this:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE ...
  • Status: Sending data
  • Time: Hundreds or thousands of seconds
  • Command: Query
  • State: Sending data

This is a clear indicator that WordPress is missing a proper index for efficient joins.


Root Cause

By default, WordPress does not create a standalone index on object_id inside the wp_term_relationships table.

Instead, it only sets a combined primary key:

PRIMARY KEY (object_id, term_taxonomy_id)

This works fine when WordPress is looking up by both object_id and term_taxonomy_id, but it is terrible for queries that only join on object_id, which is very common in themes, WooCommerce, custom post queries, and plugins.

Without a separate index on object_id, MySQL must scan the full table or the combined key every time — leading to massive performance bottlenecks.


How to Fix It

You simply need to create a separate index on object_id in the wp_term_relationships table.

Run this SQL command:

ALTER TABLE wp_term_relationships ADD INDEX idx_object_id (object_id);

If this still doesn’t help, in my case it reduced query time but wasn’t enough, add this to your functions.php

// Globally remove SQL_CALC_FOUND_ROWS from all WPDB queries
add_filter('query', function($query) {
    if (stripos($query, 'SQL_CALC_FOUND_ROWS') !== false) {
        // You can log output if you want
        // error_log('Intercepted query: ' . $query);

        // Remove SQL_CALC_FOUND_ROWS from query
        $query = str_ireplace('SQL_CALC_FOUND_ROWS', '', $query);
    }
    return $query;
});

Replace wp_ with your actual WordPress table prefix if it’s different.

This operation is safe and non-destructive. It will not affect existing data or WordPress functionality. It just improves query speed.


Immediate Benefits

  • SELECT ... LEFT JOIN wp_term_relationships ON (object_id) becomes instant instead of dragging for minutes or hours.
  • Server CPU and Disk IO usage drops significantly.
  • MariaDB/MySQL stops accumulating hundreds of “Sending data” processes.
  • WordPress pages, product listings, and category queries load much faster.

Bonus Tip: Avoid SQL_CALC_FOUND_ROWS

Many slow WordPress queries also use SQL_CALC_FOUND_ROWS, which is deprecated and inefficient.

Consider refactoring your queries to:

  • Run a SELECT COUNT(*) separately for total counts
  • Use LIMIT and OFFSET without needing FOUND_ROWS()

This improves performance even further!


Final Thoughts

This small database tweak — adding a missing index — can save your server from extreme slowdowns.
If you’re seeing Sending data issues in SHOW PROCESSLIST;, always check for missing indexes first.


Need Expert Help?

If you’re still having issues with your server or network setup, let’s fix it together. Schedule a one-on-one consultation now.

Schedule a Consultation

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *