A few weeks ago, I wrote an article titled Post Meta Abuse, but I think some have misunderstood the problem at hand.
Meta Queries are Bad?
Searching for posts via post meta is bad, but grabbing post meta is not.
For example, this is a hideously expensive/slow query:
$args = array( 'meta_key' => 'color', 'meta_value' => 'blue', 'meta_compare' => '!=' ); $query = new WP_Query( $args );
But this is super fast, almost free to run:
$color = get_post_meta( get_the_id(), 'color', true );
What’s Going On?
Post meta is optimised for fetching meta keys and values for a given post ID. If you know the ID of the post, then fetching post meta is fast! That’s what this table is built for.
A Helping Hand From WP Core
Core helps you out so that repeated calls to get_post_meta doesn’t get expensive. When you request data, it’s stored in WP_Cache so that no additional DB queries happen
More Helping Hands From WP Core?
When you fetch a post from the database, WordPress takes some initiative and fetches all of its post meta at the same time. So your code doesn’t trigger queries to fetch post meta from the database on the current post. Retrieving post meta values for the current post is essentially free. Combined with object caches such as Redis or Memcached, this makes post meta incredibly fast.
So Where’s The Problem?
Queries that search for posts. Post meta is optimised for direct accesses when you know the post ID in advance, it isn’t built for searches. That’s why taxonomy tables were added.
One of the reasons I’ve tweeted several times that ACF doesn’t scale is for this reason. ( Avoid ACF 4 for other reasons ). ACF allows you to enter huge amounts of data as post meta, which is fine for displaying posts. But if you ever try to list just the posts that have a certain field, or the posts where field X is bigger than 5, your site grinds to a halt and performance goes out the window. Install Query Monitor by John Blackbourn and watch your admin bar turn blood red with expensive database queries.
Luckily, ACF 5 and other more modern custom field systems such as Field Manager have taxonomy options. If you can force a field to be backed by taxonomy/term data, not post meta, then you can query for and search/filter for posts with that field to your hearts content.
get_post_metaon a known post is good! Super fast.
- Using the custom field parameters to search for things will give you crippling performance
Post meta is optimised for direct accesses with a known post ID. If you’re trying to search for posts with or without certain meta values, you should use a taxonomy instead.