There’s a quick rule of thumb to know if a meta_value will be a problem. Ask yourself:
“Will I be querying for this meta_value using WP_Query?”
If the answer is no, then you’ve got a perfect use case for postmeta values.
If the answer is yes, then the query is likely to have issues with performance and scalability. This is because the WordPress postmeta table has an index on meta_key, but not meta_value.
However, many use cases can be modified to avoid performance problems:
- Taxonomy Terms – Some meta_value queries can be transformed into taxonomy queries. For example, instead of using a meta_value to filter if a post should be shown to visitors with membership level “Premium”, use a custom taxonomy and a term for each of the membership levels in order to leverage the indexes.
- Binary Situations – When meta_value is set as a binary value (ex. “hide_on_homepage” = “true”), MySQL will look at every single row that has the meta_key “hide_on_homepage” in order to check for the meta_value “true”. The solution is to change this so that the mere presence of the meta_key means that the post should be hidden on the homepage. If a post shouldn’t be hidden on the homepage, simply delete the “hide_on_homepage” meta_key. This will leverage the meta_key index and can result in large performance gains.
- Non-binary Situations – Instead of setting meta_key equal to “primary_category” and meta_value equal to “sports”, you can set meta_key to “primary_category_sports”. This enables you to query by primary_category. However, instead of doing get_post_meta( $id, ‘primary_category’), you would need to iterate over possible values of primary_category with get_post_meta( $id, ‘primary_category_sports’). If you need to do both, you could use a ‘primary_category’ and a ‘primary_category_sports’ meta_key that both update when the primary category changes.
- Elasticsearch – If it’s not possible to avoid performing a meta_value query, consider using Elasticsearch instead of MySQL.