Your cart is currently empty!
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 servicesFixing 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
andOFFSET
without needingFOUND_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
Leave a Reply